{
  "openapi": "3.1.1",
  "info": {
    "title": "Quran Readings API",
    "description": "The Quran with its readings (قراءات) and recitations (روايات), composed with the scientist's rules.\n\n**Authentication** (OAuth 2.0, discovery at `/.well-known/openid-configuration`):\n* Apps reading the Quran: register a *confidential* client and use the `client_credentials` grant with scope `quran.read`.\n* Apps where a person signs in (mobile, web, control panel): register a *public* client and use the authorization code flow with PKCE.\n  Scopes `quran.content` / `quran.admin` are granted only to contributors / administrators.\n\nText offsets (highlights, word positions) are UTF-16 code units.",
    "version": "v1"
  },
  "servers": [
    {
      "url": "https://quran-api.iilm.io/"
    }
  ],
  "paths": {
    "/api/v1/readings": {
      "get": {
        "tags": [
          "Catalog"
        ],
        "summary": "Readings (القراءات)",
        "operationId": "GetReadings",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ReadingDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.read"
            ]
          }
        ]
      }
    },
    "/api/v1/readings/{readingId}/recitations": {
      "get": {
        "tags": [
          "Catalog"
        ],
        "summary": "Recitations (الروايات) of a reading",
        "operationId": "GetReadingRecitations",
        "parameters": [
          {
            "name": "readingId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/RecitationDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.read"
            ]
          }
        ]
      }
    },
    "/api/v1/recitations": {
      "get": {
        "tags": [
          "Catalog"
        ],
        "summary": "All recitations",
        "operationId": "GetRecitations",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/RecitationDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.read"
            ]
          }
        ]
      }
    },
    "/api/v1/recitations/{recitationId}/ways": {
      "get": {
        "tags": [
          "Catalog"
        ],
        "summary": "Ways (الطرق) of a recitation",
        "operationId": "GetWays",
        "parameters": [
          {
            "name": "recitationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WayDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.read"
            ]
          }
        ]
      }
    },
    "/api/v1/countings": {
      "get": {
        "tags": [
          "Catalog"
        ],
        "summary": "Verse counting systems (طرق العد)",
        "operationId": "GetCountings",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/CountingDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.read"
            ]
          }
        ]
      }
    },
    "/api/v1/chapters": {
      "get": {
        "tags": [
          "Catalog"
        ],
        "summary": "Chapters (السور)",
        "operationId": "GetChapters",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ChapterDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.read"
            ]
          }
        ]
      }
    },
    "/api/v1/chapters/{chapterId}": {
      "get": {
        "tags": [
          "Catalog"
        ],
        "summary": "A chapter",
        "operationId": "GetChapter",
        "parameters": [
          {
            "name": "chapterId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChapterDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.read"
            ]
          }
        ]
      }
    },
    "/api/v1/chapters/{chapterId}/text": {
      "get": {
        "tags": [
          "Text"
        ],
        "summary": "Composed chapter text for a reading/recitation with the viewer's filters",
        "description": "Returns the text with stop marks, sajdah/rub' marks and verse numbers, the highlighted spans for the selected filters, and the start offset of every word (for the word-readings lookup).",
        "operationId": "GetChapterText",
        "parameters": [
          {
            "name": "chapterId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "ReadingId",
            "in": "query",
            "description": "Reading (قراءة) id",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "RecitationId",
            "in": "query",
            "description": "Recitation (رواية) id; must belong to the reading",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "CountingId",
            "in": "query",
            "description": "Counting (طريقة العد) id",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "WayId",
            "in": "query",
            "description": "Way (طريق) id; 0 or omitted = none",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "DisplayFarsh",
            "in": "query",
            "description": "Highlight farsh words (اعرض الفرش)",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "PositionDifferences",
            "in": "query",
            "description": "Highlight positions where readings differ (اعرض مواضع الاختلاف)",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "ColorVerses",
            "in": "query",
            "description": "Highlight verse marks (لون الآيات)",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "ColorKufiDifferences",
            "in": "query",
            "description": "Highlight verse marks that differ in the Kufi counting (لون الاختلاف مع الكوفي); overrides colorVerses",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "CompareWithHafs",
            "in": "query",
            "description": "Highlight words that differ from Hafs (اعرض الفرق مع حفص)",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "CompareReadingId",
            "in": "query",
            "description": "Compare with this reading (اعرض الفرق مع رواية), with compareRecitationId",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "CompareRecitationId",
            "in": "query",
            "description": "Compare with this recitation, with compareReadingId",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChapterTextDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.read"
            ]
          }
        ]
      }
    },
    "/api/v1/chapters/{chapterId}/words/{wSequenceId}/readings": {
      "get": {
        "tags": [
          "Text"
        ],
        "summary": "The word used by every recitation at one position",
        "operationId": "GetWordReadings",
        "parameters": [
          {
            "name": "chapterId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "wSequenceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WordReadingDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.read"
            ]
          }
        ]
      }
    },
    "/api/v1/text-categories": {
      "get": {
        "tags": [
          "Accompanying texts"
        ],
        "summary": "Categories of accompanying texts (tafseer, translation, ...)",
        "operationId": "GetTextCategories",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TextCategoryDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.read"
            ]
          }
        ]
      }
    },
    "/api/v1/text-categories/{categoryId}/subcategories": {
      "get": {
        "tags": [
          "Accompanying texts"
        ],
        "summary": "Sub-categories of a text category",
        "operationId": "GetTextSubCategories",
        "parameters": [
          {
            "name": "categoryId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TextSubCategoryDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.read"
            ]
          }
        ]
      }
    },
    "/api/v1/chapters/{chapterId}/accompanying-texts": {
      "get": {
        "tags": [
          "Accompanying texts"
        ],
        "summary": "Accompanying texts of a chapter",
        "operationId": "GetAccompanyingTexts",
        "parameters": [
          {
            "name": "chapterId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "CategoryId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "SubCategoryId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "WSequenceId",
            "in": "query",
            "description": "Word position",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "WholeChapter",
            "in": "query",
            "description": "All values of the sub-category for the chapter",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "WholeSubCategories",
            "in": "query",
            "description": "All sub-categories at the position",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "SearchForLastMatch",
            "in": "query",
            "description": "If nothing is stored at the position, return the last value before it",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.read"
            ]
          }
        ]
      }
    },
    "/api/v1/words/search": {
      "get": {
        "tags": [
          "Research"
        ],
        "summary": "Stored occurrences of words starting with a prefix (max 500)",
        "operationId": "SearchWords",
        "parameters": [
          {
            "name": "prefix",
            "in": "query",
            "description": "Beginning of the word, 2-50 characters",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WordOccurrenceDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.read"
            ]
          }
        ]
      }
    },
    "/api/v1/statistics/hafs-differences": {
      "get": {
        "tags": [
          "Research"
        ],
        "summary": "Words that differ from Hafs, per reading/recitation",
        "operationId": "GetHafsDifferences",
        "parameters": [
          {
            "name": "chapterId",
            "in": "query",
            "description": "Chapter; omit for the whole Quran",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/HafsDifferenceDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.read"
            ]
          }
        ]
      }
    },
    "/api/v1/statistics/word-frequencies": {
      "get": {
        "tags": [
          "Research"
        ],
        "summary": "Word frequencies over all recitations",
        "operationId": "GetWordFrequencies",
        "parameters": [
          {
            "name": "chapterId",
            "in": "query",
            "description": "Chapter; omit for the whole Quran",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WordFrequencyDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.read"
            ]
          }
        ]
      }
    },
    "/api/v1/statistics/recitation-words": {
      "get": {
        "tags": [
          "Research"
        ],
        "summary": "Word frequencies of one recitation",
        "operationId": "GetRecitationWordFrequencies",
        "parameters": [
          {
            "name": "readingId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "recitationId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "chapterId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WordFrequencyDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.read"
            ]
          }
        ]
      }
    },
    "/api/v1/content/readings": {
      "post": {
        "tags": [
          "Content"
        ],
        "summary": "Add a reading (returns the existing id if the name exists)",
        "operationId": "CreateReading",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateReadingRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.content"
            ]
          }
        ]
      }
    },
    "/api/v1/content/recitations": {
      "post": {
        "tags": [
          "Content"
        ],
        "summary": "Add a recitation to a reading (returns the existing id if it exists)",
        "operationId": "CreateRecitation",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateRecitationRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.content"
            ]
          }
        ]
      }
    },
    "/api/v1/content/chapters/{chapterId}/words/{wSequenceId}": {
      "put": {
        "tags": [
          "Content"
        ],
        "summary": "Change the word of one recitation at one position",
        "operationId": "UpdateChapterWord",
        "parameters": [
          {
            "name": "chapterId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "wSequenceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateChapterWordRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "No Content"
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.content"
            ]
          }
        ]
      }
    },
    "/api/v1/content/audit": {
      "get": {
        "tags": [
          "Content"
        ],
        "summary": "Recent content changes (max 500)",
        "operationId": "GetAuditLog",
        "parameters": [
          {
            "name": "take",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "chapterId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AuditEntryDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.content"
            ]
          }
        ]
      }
    },
    "/api/v1/content/chapters/{chapterId}": {
      "delete": {
        "tags": [
          "Content"
        ],
        "summary": "Remove all words and counting marks of a chapter (admin)",
        "operationId": "DeleteChapterContent",
        "parameters": [
          {
            "name": "chapterId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.content",
              "quran.admin"
            ]
          }
        ]
      },
      "put": {
        "tags": [
          "Import & export"
        ],
        "summary": "Replace the words and counting marks of a chapter (JSON)",
        "description": "Same process as the scientist's upload tool, in one transaction: readings/recitations are added if missing, the chapter is cleared, every position is rolled up into differentiation levels (majority word stored once at the most general level) and stored with AddReadyWords, then the counting marks are added.",
        "operationId": "ImportChapter",
        "parameters": [
          {
            "name": "chapterId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChapterImport"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChapterImportSummary"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.content"
            ]
          }
        ]
      }
    },
    "/api/v1/content/chapters/import/excel": {
      "post": {
        "tags": [
          "Import & export"
        ],
        "summary": "Replace a chapter from the upload tool's Excel workbook (.xls/.xlsx)",
        "description": "Sheet 'works': chapter, position, one column per recitation (header = reading, row 2 = recitation); sheet 'Sheet1': counting marks. The chapter number is read from the file.",
        "operationId": "ImportChapterWorkbook",
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "required": [
                  "file"
                ],
                "type": "object",
                "properties": {
                  "file": {
                    "$ref": "#/components/schemas/IFormFile"
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChapterImportSummary"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.content"
            ]
          }
        ]
      }
    },
    "/api/v1/content/chapters/{chapterId}/export": {
      "get": {
        "tags": [
          "Import & export"
        ],
        "summary": "The chapter's words for every recitation and its counting marks (JSON, re-importable)",
        "operationId": "ExportChapter",
        "parameters": [
          {
            "name": "chapterId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChapterImport"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.content"
            ]
          }
        ]
      }
    },
    "/api/v1/content/chapters/{chapterId}/export/excel": {
      "get": {
        "tags": [
          "Import & export"
        ],
        "summary": "The chapter in the upload tool's Excel format (re-importable)",
        "operationId": "ExportChapterWorkbook",
        "parameters": [
          {
            "name": "chapterId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.content"
            ]
          }
        ]
      }
    },
    "/api/v1/content/text-categories": {
      "post": {
        "tags": [
          "Content"
        ],
        "summary": "Add an accompanying-text category (admin; returns the existing id if the name exists)",
        "operationId": "CreateTextCategory",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateTextCategoryRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.content",
              "quran.admin"
            ]
          }
        ]
      }
    },
    "/api/v1/content/text-subcategories": {
      "post": {
        "tags": [
          "Content"
        ],
        "summary": "Add an accompanying-text sub-category (returns the existing id if it exists)",
        "operationId": "CreateTextSubCategory",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateTextSubCategoryRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.content"
            ]
          }
        ]
      }
    },
    "/api/v1/content/chapters/{chapterId}/accompanying-texts": {
      "post": {
        "tags": [
          "Content"
        ],
        "summary": "Add an accompanying text at a position (409 if one exists)",
        "operationId": "AddAccompanyingText",
        "parameters": [
          {
            "name": "chapterId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddAccompanyingTextRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "No Content"
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.content"
            ]
          }
        ]
      },
      "delete": {
        "tags": [
          "Content"
        ],
        "summary": "Remove all accompanying texts of a chapter (admin)",
        "operationId": "DeleteChapterAccompanyingTexts",
        "parameters": [
          {
            "name": "chapterId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.content",
              "quran.admin"
            ]
          }
        ]
      }
    },
    "/api/v1/content/chapters/{chapterId}/accompanying-texts/verses": {
      "post": {
        "tags": [
          "Import & export"
        ],
        "summary": "Add one text per verse (e.g. a tafseer); each is stored at the first word of its verse",
        "operationId": "AddVerseTexts",
        "parameters": [
          {
            "name": "chapterId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddVerseTextsRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnonymousTypeOfint"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.content"
            ]
          }
        ]
      }
    },
    "/api/v1/content/accompanying-texts/import/excel": {
      "post": {
        "tags": [
          "Import & export"
        ],
        "summary": "Replace a chapter's accompanying texts from the upload tool's Excel workbook",
        "description": "Sheets 'Tafseer', 'RasmOthmani', 'Targamaat': chapter, position, one column per sub-category (header = name).",
        "operationId": "ImportTextsWorkbook",
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "required": [
                  "file"
                ],
                "type": "object",
                "properties": {
                  "file": {
                    "$ref": "#/components/schemas/IFormFile"
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TextsImportSummary"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.content"
            ]
          }
        ]
      }
    },
    "/api/v1/me": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "The signed-in person's account",
        "operationId": "GetMyAccount",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/me/password": {
      "post": {
        "tags": [
          "Account"
        ],
        "summary": "Change the signed-in person's password",
        "operationId": "ChangeMyPassword",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChangePasswordRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "No Content"
          }
        }
      }
    },
    "/api/v1/admin/users": {
      "get": {
        "tags": [
          "Users"
        ],
        "summary": "All users",
        "operationId": "GetUsers",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/UserDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.admin"
            ]
          }
        ]
      },
      "post": {
        "tags": [
          "Users"
        ],
        "summary": "Create a user with roles (Admin, Contributor, User)",
        "operationId": "CreateUser",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateUserRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.admin"
            ]
          }
        ]
      }
    },
    "/api/v1/admin/users/{userId}/roles": {
      "put": {
        "tags": [
          "Users"
        ],
        "summary": "Replace the roles of a user",
        "operationId": "SetUserRoles",
        "parameters": [
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateUserRolesRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.admin"
            ]
          }
        ]
      }
    },
    "/api/v1/admin/users/{userId}/lock": {
      "put": {
        "tags": [
          "Users"
        ],
        "summary": "Lock or unlock a user",
        "operationId": "SetUserLock",
        "parameters": [
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetUserLockRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.admin"
            ]
          }
        ]
      }
    },
    "/api/v1/admin/users/{userId}": {
      "delete": {
        "tags": [
          "Users"
        ],
        "summary": "Delete a user",
        "operationId": "DeleteUser",
        "parameters": [
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.admin"
            ]
          }
        ]
      }
    },
    "/api/v1/admin/clients": {
      "get": {
        "tags": [
          "Client applications"
        ],
        "summary": "Registered OAuth client applications",
        "operationId": "GetClients",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ClientDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.admin"
            ]
          }
        ]
      },
      "post": {
        "tags": [
          "Client applications"
        ],
        "summary": "Register an app; a confidential client's secret is returned only once",
        "operationId": "CreateClient",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateClientRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedClientDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.admin"
            ]
          }
        ]
      }
    },
    "/api/v1/admin/clients/{clientId}": {
      "delete": {
        "tags": [
          "Client applications"
        ],
        "summary": "Revoke an app",
        "operationId": "DeleteClient",
        "parameters": [
          {
            "name": "clientId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "401": {
            "description": "Missing or invalid access token"
          },
          "403": {
            "description": "The token lacks the required scope or role"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth2": [
              "quran.admin"
            ]
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "AddAccompanyingTextRequest": {
        "required": [
          "categoryId",
          "subCategoryId",
          "wSequenceId",
          "value"
        ],
        "type": "object",
        "properties": {
          "categoryId": {
            "type": "integer",
            "format": "int32"
          },
          "subCategoryId": {
            "type": "integer",
            "format": "int32"
          },
          "wSequenceId": {
            "type": "integer",
            "format": "int32"
          },
          "value": {
            "type": "string"
          }
        }
      },
      "AddVerseTextsRequest": {
        "required": [
          "categoryId",
          "subCategoryId",
          "countingId",
          "verses",
          "replace"
        ],
        "type": "object",
        "properties": {
          "categoryId": {
            "type": "integer",
            "format": "int32"
          },
          "subCategoryId": {
            "type": "integer",
            "format": "int32"
          },
          "countingId": {
            "type": "integer",
            "format": "int32"
          },
          "verses": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "replace": {
            "type": "boolean"
          }
        }
      },
      "AnonymousTypeOfint": {
        "required": [
          "stored"
        ],
        "type": "object",
        "properties": {
          "stored": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "AuditEntryDto": {
        "required": [
          "id",
          "occurredAt",
          "userId",
          "userName",
          "action",
          "chapterId",
          "details"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "occurredAt": {
            "type": "string",
            "format": "date-time"
          },
          "userId": {
            "type": "string"
          },
          "userName": {
            "type": "string"
          },
          "action": {
            "type": "string"
          },
          "chapterId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "details": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "ChangePasswordRequest": {
        "required": [
          "currentPassword",
          "newPassword"
        ],
        "type": "object",
        "properties": {
          "currentPassword": {
            "type": "string"
          },
          "newPassword": {
            "type": "string"
          }
        }
      },
      "ChapterDto": {
        "required": [
          "id",
          "name"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "ChapterImport": {
        "required": [
          "chapterId",
          "recitations"
        ],
        "type": "object",
        "properties": {
          "chapterId": {
            "type": "integer",
            "format": "int32"
          },
          "recitations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RecitationWords"
            }
          },
          "countings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WordCounting"
            }
          }
        }
      },
      "ChapterImportSummary": {
        "required": [
          "chapterId",
          "recitations",
          "positions",
          "countingMarks"
        ],
        "type": "object",
        "properties": {
          "chapterId": {
            "type": "integer",
            "format": "int32"
          },
          "recitations": {
            "type": "integer",
            "format": "int32"
          },
          "positions": {
            "type": "integer",
            "format": "int32"
          },
          "countingMarks": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "ChapterTextDto": {
        "required": [
          "chapterId",
          "readingId",
          "recitationId",
          "wayId",
          "countingId",
          "comparedWith",
          "text",
          "highlights",
          "words"
        ],
        "type": "object",
        "properties": {
          "chapterId": {
            "type": "integer",
            "format": "int32"
          },
          "readingId": {
            "type": "integer",
            "format": "int32"
          },
          "recitationId": {
            "type": "integer",
            "format": "int32"
          },
          "wayId": {
            "type": "integer",
            "format": "int32"
          },
          "countingId": {
            "type": "integer",
            "format": "int32"
          },
          "comparedWith": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/ComparisonDto"
              }
            ]
          },
          "text": {
            "type": "string"
          },
          "highlights": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HighlightDto"
            }
          },
          "words": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WordPositionDto"
            }
          }
        }
      },
      "ClientDto": {
        "required": [
          "clientId",
          "displayName",
          "type",
          "scopes",
          "redirectUris"
        ],
        "type": "object",
        "properties": {
          "clientId": {
            "type": "string"
          },
          "displayName": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "redirectUris": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "ComparisonDto": {
        "required": [
          "readingId",
          "recitationId",
          "wayId"
        ],
        "type": "object",
        "properties": {
          "readingId": {
            "type": "integer",
            "format": "int32"
          },
          "recitationId": {
            "type": "integer",
            "format": "int32"
          },
          "wayId": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "CountingDto": {
        "required": [
          "id",
          "name"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "CreateClientRequest": {
        "required": [
          "clientId",
          "displayName",
          "type",
          "scopes",
          "redirectUris",
          "postLogoutRedirectUris"
        ],
        "type": "object",
        "properties": {
          "clientId": {
            "type": "string"
          },
          "displayName": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "scopes": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "type": "string"
            }
          },
          "redirectUris": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "type": "string"
            }
          },
          "postLogoutRedirectUris": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "type": "string"
            }
          }
        }
      },
      "CreatedClientDto": {
        "required": [
          "clientId",
          "clientSecret"
        ],
        "type": "object",
        "properties": {
          "clientId": {
            "type": "string"
          },
          "clientSecret": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "CreateReadingRequest": {
        "required": [
          "name"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          }
        }
      },
      "CreateRecitationRequest": {
        "required": [
          "name",
          "readingId"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "readingId": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "CreateTextCategoryRequest": {
        "required": [
          "name"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          }
        }
      },
      "CreateTextSubCategoryRequest": {
        "required": [
          "categoryId",
          "name"
        ],
        "type": "object",
        "properties": {
          "categoryId": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "CreateUserRequest": {
        "required": [
          "email",
          "password",
          "displayName",
          "roles"
        ],
        "type": "object",
        "properties": {
          "email": {
            "type": "string"
          },
          "password": {
            "type": "string"
          },
          "displayName": {
            "type": [
              "null",
              "string"
            ]
          },
          "roles": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "HafsDifferenceDto": {
        "required": [
          "chapterName",
          "wSequenceId",
          "wordId",
          "word",
          "hafsWordId",
          "readingName",
          "recitationName"
        ],
        "type": "object",
        "properties": {
          "chapterName": {
            "type": "string"
          },
          "wSequenceId": {
            "type": "integer",
            "format": "int32"
          },
          "wordId": {
            "type": "integer",
            "format": "int32"
          },
          "word": {
            "type": "string"
          },
          "hafsWordId": {
            "type": "integer",
            "format": "int32"
          },
          "readingName": {
            "type": [
              "null",
              "string"
            ]
          },
          "recitationName": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "HighlightDto": {
        "required": [
          "start",
          "length",
          "type"
        ],
        "type": "object",
        "properties": {
          "start": {
            "type": "integer",
            "format": "int32"
          },
          "length": {
            "type": "integer",
            "format": "int32"
          },
          "type": {
            "$ref": "#/components/schemas/HighlightType"
          }
        }
      },
      "HighlightType": {
        "enum": [
          "Farsh",
          "RecitationDifference",
          "TwoRecitationDifference",
          "Verse",
          "KufiDifference",
          "Intersection"
        ]
      },
      "HttpValidationProblemDetails": {
        "type": "object",
        "properties": {
          "type": {
            "type": [
              "null",
              "string"
            ]
          },
          "title": {
            "type": [
              "null",
              "string"
            ]
          },
          "status": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "detail": {
            "type": [
              "null",
              "string"
            ]
          },
          "instance": {
            "type": [
              "null",
              "string"
            ]
          },
          "errors": {
            "type": "object",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          }
        }
      },
      "IdResponse": {
        "required": [
          "id"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "IFormFile": {
        "type": "string",
        "format": "binary"
      },
      "ImportedWord": {
        "required": [
          "wSequenceId",
          "wSequenceId2",
          "word"
        ],
        "type": "object",
        "properties": {
          "wSequenceId": {
            "type": "integer",
            "format": "int32"
          },
          "wSequenceId2": {
            "type": "integer",
            "format": "int32"
          },
          "word": {
            "type": "string"
          }
        }
      },
      "ReadingDto": {
        "required": [
          "id",
          "name"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "RecitationDto": {
        "required": [
          "id",
          "name",
          "readingId"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": "string"
          },
          "readingId": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "RecitationWords": {
        "required": [
          "readingName",
          "recitationName",
          "words"
        ],
        "type": "object",
        "properties": {
          "readingName": {
            "type": "string"
          },
          "recitationName": {
            "type": "string"
          },
          "words": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ImportedWord"
            }
          }
        }
      },
      "SetUserLockRequest": {
        "required": [
          "locked"
        ],
        "type": "object",
        "properties": {
          "locked": {
            "type": "boolean"
          }
        }
      },
      "TextCategoryDto": {
        "required": [
          "id",
          "name"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "TextsImportSummary": {
        "required": [
          "chapterId",
          "subCategories",
          "texts"
        ],
        "type": "object",
        "properties": {
          "chapterId": {
            "type": "integer",
            "format": "int32"
          },
          "subCategories": {
            "type": "integer",
            "format": "int32"
          },
          "texts": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "TextSubCategoryDto": {
        "required": [
          "id",
          "name"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "UpdateChapterWordRequest": {
        "required": [
          "readingId",
          "recitationId",
          "oldWordId",
          "word"
        ],
        "type": "object",
        "properties": {
          "readingId": {
            "type": "integer",
            "format": "int32"
          },
          "recitationId": {
            "type": "integer",
            "format": "int32"
          },
          "wayId": {
            "type": "integer",
            "format": "int32"
          },
          "wSequenceId2": {
            "type": "integer",
            "format": "int32"
          },
          "oldWordId": {
            "type": "integer",
            "format": "int32"
          },
          "word": {
            "type": "string"
          }
        }
      },
      "UpdateUserRolesRequest": {
        "required": [
          "roles"
        ],
        "type": "object",
        "properties": {
          "roles": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "UserDto": {
        "required": [
          "id",
          "email",
          "displayName",
          "roles",
          "isLockedOut"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "displayName": {
            "type": [
              "null",
              "string"
            ]
          },
          "roles": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "isLockedOut": {
            "type": "boolean"
          }
        }
      },
      "WayDto": {
        "required": [
          "id",
          "name",
          "recitationId",
          "parentId",
          "isLeaf"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": "string"
          },
          "recitationId": {
            "type": "integer",
            "format": "int32"
          },
          "parentId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "isLeaf": {
            "type": "boolean"
          }
        }
      },
      "WordCounting": {
        "required": [
          "wSequenceId",
          "countingId"
        ],
        "type": "object",
        "properties": {
          "wSequenceId": {
            "type": "integer",
            "format": "int32"
          },
          "countingId": {
            "type": "integer",
            "format": "int32"
          },
          "isVerse": {
            "type": "boolean"
          },
          "isSajdah": {
            "type": "boolean"
          },
          "isRob3": {
            "type": "boolean"
          },
          "stopageMark": {
            "type": [
              "null",
              "string"
            ]
          },
          "isFarsh": {
            "type": "boolean"
          },
          "isKufiDifferent": {
            "type": "boolean"
          }
        }
      },
      "WordFrequencyDto": {
        "required": [
          "wordId",
          "word",
          "count"
        ],
        "type": "object",
        "properties": {
          "wordId": {
            "type": "integer",
            "format": "int32"
          },
          "word": {
            "type": "string"
          },
          "count": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "WordOccurrenceDto": {
        "required": [
          "chapterId",
          "chapterName",
          "wSequenceId",
          "wordId",
          "word",
          "level",
          "levelId",
          "readingName",
          "recitationName",
          "differentDown"
        ],
        "type": "object",
        "properties": {
          "chapterId": {
            "type": "integer",
            "format": "int32"
          },
          "chapterName": {
            "type": "string"
          },
          "wSequenceId": {
            "type": "integer",
            "format": "int32"
          },
          "wordId": {
            "type": "integer",
            "format": "int32"
          },
          "word": {
            "type": "string"
          },
          "level": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "levelId": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          },
          "readingName": {
            "type": [
              "null",
              "string"
            ]
          },
          "recitationName": {
            "type": [
              "null",
              "string"
            ]
          },
          "differentDown": {
            "type": [
              "null",
              "integer"
            ],
            "format": "int32"
          }
        }
      },
      "WordPositionDto": {
        "required": [
          "start",
          "wSequenceId",
          "wordId",
          "wSequenceId2"
        ],
        "type": "object",
        "properties": {
          "start": {
            "type": "integer",
            "format": "int32"
          },
          "wSequenceId": {
            "type": "integer",
            "format": "int32"
          },
          "wordId": {
            "type": "integer",
            "format": "int32"
          },
          "wSequenceId2": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "WordReadingDto": {
        "required": [
          "readingName",
          "recitationName",
          "word",
          "wordGroup"
        ],
        "type": "object",
        "properties": {
          "readingName": {
            "type": "string"
          },
          "recitationName": {
            "type": "string"
          },
          "word": {
            "type": "string"
          },
          "wordGroup": {
            "type": "integer",
            "format": "int64"
          }
        }
      }
    },
    "securitySchemes": {
      "oauth2": {
        "type": "oauth2",
        "description": "OAuth 2.0",
        "flows": {
          "clientCredentials": {
            "tokenUrl": "/connect/token",
            "scopes": {
              "quran.read": "Read the Quran"
            }
          },
          "authorizationCode": {
            "authorizationUrl": "/connect/authorize",
            "tokenUrl": "/connect/token",
            "scopes": {
              "quran.read": "Read the Quran",
              "quran.content": "Edit content (contributors, administrators)",
              "quran.admin": "Manage users and applications (administrators)"
            }
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "Catalog"
    },
    {
      "name": "Text"
    },
    {
      "name": "Accompanying texts"
    },
    {
      "name": "Research"
    },
    {
      "name": "Content"
    },
    {
      "name": "Import & export"
    },
    {
      "name": "Account"
    },
    {
      "name": "Users"
    },
    {
      "name": "Client applications"
    }
  ]
}