diff --git a/package.json b/package.json
index b5cc2457c721ebdd6207b35d74b871fd96823b3f..42b8fdf5e4e563eb2ddc342edb4a2f9794e42222 100644
--- a/package.json
+++ b/package.json
@@ -89,7 +89,7 @@
 		"autwh": "0.1.0",
 		"bcryptjs": "2.4.3",
 		"bootstrap-vue": "2.0.0-rc.11",
-		"cafy": "8.0.0",
+		"cafy": "11.0.0",
 		"chalk": "2.4.1",
 		"crc-32": "1.2.0",
 		"css-loader": "0.28.11",
diff --git a/src/cafy-id.ts b/src/cafy-id.ts
index dac0f97bd2e815ae0e8960577e9a7408f5c100ed..9b7f4f97bfce06ead977792e035c04ea56899eac 100644
--- a/src/cafy-id.ts
+++ b/src/cafy-id.ts
@@ -1,5 +1,5 @@
 import * as mongo from 'mongodb';
-import { Query } from 'cafy';
+import { Context } from 'cafy';
 
 export const isAnId = (x: any) => mongo.ObjectID.isValid(x);
 export const isNotAnId = (x: any) => !isAnId(x);
@@ -7,7 +7,7 @@ export const isNotAnId = (x: any) => !isAnId(x);
 /**
  * ID
  */
-export default class ID extends Query<mongo.ObjectID> {
+export default class ID extends Context<mongo.ObjectID> {
 	constructor() {
 		super();
 
diff --git a/src/server/api/endpoints/aggregation/posts.ts b/src/server/api/endpoints/aggregation/posts.ts
index 48e344312deb5be0d41032b3acd35b4459f9cbac..5de5789954a789047a5e866b45899ca76e5c76c1 100644
--- a/src/server/api/endpoints/aggregation/posts.ts
+++ b/src/server/api/endpoints/aggregation/posts.ts
@@ -6,7 +6,7 @@ import Note from '../../../../models/note';
  */
 module.exports = (params: any) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 365, limitErr] = $.num.optional().range(1, 365).get(params.limit);
+	const [limit = 365, limitErr] = $.num.optional.range(1, 365).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	const datas = await Note
diff --git a/src/server/api/endpoints/aggregation/users.ts b/src/server/api/endpoints/aggregation/users.ts
index c084404d0ac9350745e65944c5616f7fc699ed52..3ab96b66d47b902838f05e4176893a9a0a5eeaa7 100644
--- a/src/server/api/endpoints/aggregation/users.ts
+++ b/src/server/api/endpoints/aggregation/users.ts
@@ -6,7 +6,7 @@ import User from '../../../../models/user';
  */
 module.exports = (params: any) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 365, limitErr] = $.num.optional().range(1, 365).get(params.limit);
+	const [limit = 365, limitErr] = $.num.optional.range(1, 365).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	const users = await User
diff --git a/src/server/api/endpoints/aggregation/users/activity.ts b/src/server/api/endpoints/aggregation/users/activity.ts
index d4c716d65b304652227fa37f49468dde3cb4e665..98c7d3a1dc2a9fbc811628551e0891d21af5f4c1 100644
--- a/src/server/api/endpoints/aggregation/users/activity.ts
+++ b/src/server/api/endpoints/aggregation/users/activity.ts
@@ -9,7 +9,7 @@ import Note from '../../../../../models/note';
  */
 module.exports = (params: any) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 365, limitErr] = $.num.optional().range(1, 365).get(params.limit);
+	const [limit = 365, limitErr] = $.num.optional.range(1, 365).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'userId' parameter
diff --git a/src/server/api/endpoints/app/create.ts b/src/server/api/endpoints/app/create.ts
index c7bc91a079dbd26e31dd9696ba6a2f5f68efdf93..5da87e5a3a15f85d0e54093acb4675746bd49f3e 100644
--- a/src/server/api/endpoints/app/create.ts
+++ b/src/server/api/endpoints/app/create.ts
@@ -78,7 +78,7 @@ module.exports = async (params: any, user: ILocalUser) => new Promise(async (res
 
 	// Get 'callbackUrl' parameter
 	// TODO: Check it is valid url
-	const [callbackUrl = null, callbackUrlErr] = $.str.optional().nullable().get(params.callbackUrl);
+	const [callbackUrl = null, callbackUrlErr] = $.str.optional.nullable.get(params.callbackUrl);
 	if (callbackUrlErr) return rej('invalid callbackUrl param');
 
 	// Generate secret
diff --git a/src/server/api/endpoints/app/show.ts b/src/server/api/endpoints/app/show.ts
index 2b98a3f142756d3e211f7e8d97bc17f642528d1a..982c87c4ec3d05db59e199af2df77623b27e0014 100644
--- a/src/server/api/endpoints/app/show.ts
+++ b/src/server/api/endpoints/app/show.ts
@@ -39,11 +39,11 @@ module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async
 	const isSecure = user != null && app == null;
 
 	// Get 'appId' parameter
-	const [appId, appIdErr] = $.type(ID).optional().get(params.appId);
+	const [appId, appIdErr] = $.type(ID).optional.get(params.appId);
 	if (appIdErr) return rej('invalid appId param');
 
 	// Get 'nameId' parameter
-	const [nameId, nameIdErr] = $.str.optional().get(params.nameId);
+	const [nameId, nameIdErr] = $.str.optional.get(params.nameId);
 	if (nameIdErr) return rej('invalid nameId param');
 
 	if (appId === undefined && nameId === undefined) {
diff --git a/src/server/api/endpoints/drive/files.ts b/src/server/api/endpoints/drive/files.ts
index efce750747021e0d417c4cb4e2755320a2ba75f5..fa99c4a51b40b8c8876f51105c89f9fa5eb8a76c 100644
--- a/src/server/api/endpoints/drive/files.ts
+++ b/src/server/api/endpoints/drive/files.ts
@@ -7,15 +7,15 @@ import { ILocalUser } from '../../../../models/user';
  */
 module.exports = async (params: any, user: ILocalUser) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) throw 'invalid limit param';
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) throw 'invalid sinceId param';
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) throw 'invalid untilId param';
 
 	// Check if both of sinceId and untilId is specified
@@ -24,11 +24,11 @@ module.exports = async (params: any, user: ILocalUser) => {
 	}
 
 	// Get 'folderId' parameter
-	const [folderId = null, folderIdErr] = $.type(ID).optional().nullable().get(params.folderId);
+	const [folderId = null, folderIdErr] = $.type(ID).optional.nullable.get(params.folderId);
 	if (folderIdErr) throw 'invalid folderId param';
 
 	// Get 'type' parameter
-	const [type, typeErr] = $.str.optional().match(/^[a-zA-Z\/\-\*]+$/).get(params.type);
+	const [type, typeErr] = $.str.optional.match(/^[a-zA-Z\/\-\*]+$/).get(params.type);
 	if (typeErr) throw 'invalid type param';
 
 	// Construct query
diff --git a/src/server/api/endpoints/drive/files/create.ts b/src/server/api/endpoints/drive/files/create.ts
index db2626af09c94f6f0a93bb46229257287a63d635..4c348c13024471cdfb2aafae8ee98feab000a91d 100644
--- a/src/server/api/endpoints/drive/files/create.ts
+++ b/src/server/api/endpoints/drive/files/create.ts
@@ -28,7 +28,7 @@ module.exports = async (file: any, params: any, user: ILocalUser): Promise<any>
 	}
 
 	// Get 'folderId' parameter
-	const [folderId = null, folderIdErr] = $.type(ID).optional().nullable().get(params.folderId);
+	const [folderId = null, folderIdErr] = $.type(ID).optional.nullable.get(params.folderId);
 	if (folderIdErr) throw 'invalid folderId param';
 
 	function cleanup() {
diff --git a/src/server/api/endpoints/drive/files/find.ts b/src/server/api/endpoints/drive/files/find.ts
index 75ab91f0a1f0c4d403e3a5a960e1d7fc353342bf..dfca4e039585b99390f80440f8a39db080820e95 100644
--- a/src/server/api/endpoints/drive/files/find.ts
+++ b/src/server/api/endpoints/drive/files/find.ts
@@ -11,7 +11,7 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej)
 	if (nameErr) return rej('invalid name param');
 
 	// Get 'folderId' parameter
-	const [folderId = null, folderIdErr] = $.type(ID).optional().nullable().get(params.folderId);
+	const [folderId = null, folderIdErr] = $.type(ID).optional.nullable.get(params.folderId);
 	if (folderIdErr) return rej('invalid folderId param');
 
 	// Issue query
diff --git a/src/server/api/endpoints/drive/files/update.ts b/src/server/api/endpoints/drive/files/update.ts
index 825683b214ab85e535c2083dbb496daf08dfd167..76656beaa005b6dfb5eb3b6ebaf9e61a7c5b1efd 100644
--- a/src/server/api/endpoints/drive/files/update.ts
+++ b/src/server/api/endpoints/drive/files/update.ts
@@ -24,12 +24,12 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej)
 	}
 
 	// Get 'name' parameter
-	const [name, nameErr] = $.str.optional().pipe(validateFileName).get(params.name);
+	const [name, nameErr] = $.str.optional.pipe(validateFileName).get(params.name);
 	if (nameErr) return rej('invalid name param');
 	if (name) file.filename = name;
 
 	// Get 'folderId' parameter
-	const [folderId, folderIdErr] = $.type(ID).optional().nullable().get(params.folderId);
+	const [folderId, folderIdErr] = $.type(ID).optional.nullable.get(params.folderId);
 	if (folderIdErr) return rej('invalid folderId param');
 
 	if (folderId !== undefined) {
diff --git a/src/server/api/endpoints/drive/files/upload_from_url.ts b/src/server/api/endpoints/drive/files/upload_from_url.ts
index cb617d851faf3936f1cbd74b53bbfc728a0ccdfe..442a0d39403071998a4cc28c87d001a4597f2924 100644
--- a/src/server/api/endpoints/drive/files/upload_from_url.ts
+++ b/src/server/api/endpoints/drive/files/upload_from_url.ts
@@ -16,7 +16,7 @@ module.exports = async (params: any, user: ILocalUser): Promise<any> => {
 	if (urlErr) throw 'invalid url param';
 
 	// Get 'folderId' parameter
-	const [folderId = null, folderIdErr] = $.type(ID).optional().nullable().get(params.folderId);
+	const [folderId = null, folderIdErr] = $.type(ID).optional.nullable.get(params.folderId);
 	if (folderIdErr) throw 'invalid folderId param';
 
 	return pack(await uploadFromUrl(url, user, folderId));
diff --git a/src/server/api/endpoints/drive/folders.ts b/src/server/api/endpoints/drive/folders.ts
index 34137789500dc39786208576221dabff442677a3..878c747a42842e626df07a6d1e66363b1e2b20f0 100644
--- a/src/server/api/endpoints/drive/folders.ts
+++ b/src/server/api/endpoints/drive/folders.ts
@@ -7,15 +7,15 @@ import { ILocalUser } from '../../../../models/user';
  */
 module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Check if both of sinceId and untilId is specified
@@ -24,7 +24,7 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej)
 	}
 
 	// Get 'folderId' parameter
-	const [folderId = null, folderIdErr] = $.type(ID).optional().nullable().get(params.folderId);
+	const [folderId = null, folderIdErr] = $.type(ID).optional.nullable.get(params.folderId);
 	if (folderIdErr) return rej('invalid folderId param');
 
 	// Construct query
diff --git a/src/server/api/endpoints/drive/folders/create.ts b/src/server/api/endpoints/drive/folders/create.ts
index 8f06b0f6683e600d78736e0c765c361e791e2aa7..c06a40ded3e3f15076d36fff17dc047c98c2316d 100644
--- a/src/server/api/endpoints/drive/folders/create.ts
+++ b/src/server/api/endpoints/drive/folders/create.ts
@@ -8,11 +8,11 @@ import { ILocalUser } from '../../../../../models/user';
  */
 module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'name' parameter
-	const [name = '無題のフォルダー', nameErr] = $.str.optional().pipe(isValidFolderName).get(params.name);
+	const [name = '無題のフォルダー', nameErr] = $.str.optional.pipe(isValidFolderName).get(params.name);
 	if (nameErr) return rej('invalid name param');
 
 	// Get 'parentId' parameter
-	const [parentId = null, parentIdErr] = $.type(ID).optional().nullable().get(params.parentId);
+	const [parentId = null, parentIdErr] = $.type(ID).optional.nullable.get(params.parentId);
 	if (parentIdErr) return rej('invalid parentId param');
 
 	// If the parent folder is specified
diff --git a/src/server/api/endpoints/drive/folders/find.ts b/src/server/api/endpoints/drive/folders/find.ts
index b3238b5c327c953e2240488a3ff42354e32ada39..414202ccd68b9b9eb8dbe788868554cb306a51a6 100644
--- a/src/server/api/endpoints/drive/folders/find.ts
+++ b/src/server/api/endpoints/drive/folders/find.ts
@@ -11,7 +11,7 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej)
 	if (nameErr) return rej('invalid name param');
 
 	// Get 'parentId' parameter
-	const [parentId = null, parentIdErr] = $.type(ID).optional().nullable().get(params.parentId);
+	const [parentId = null, parentIdErr] = $.type(ID).optional.nullable.get(params.parentId);
 	if (parentIdErr) return rej('invalid parentId param');
 
 	// Issue query
diff --git a/src/server/api/endpoints/drive/folders/update.ts b/src/server/api/endpoints/drive/folders/update.ts
index f126c09f5b221c891d029c9708663cea70106d70..20675771fefe56891324e1578f727cdf5c8255ec 100644
--- a/src/server/api/endpoints/drive/folders/update.ts
+++ b/src/server/api/endpoints/drive/folders/update.ts
@@ -23,12 +23,12 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej)
 	}
 
 	// Get 'name' parameter
-	const [name, nameErr] = $.str.optional().pipe(isValidFolderName).get(params.name);
+	const [name, nameErr] = $.str.optional.pipe(isValidFolderName).get(params.name);
 	if (nameErr) return rej('invalid name param');
 	if (name) folder.name = name;
 
 	// Get 'parentId' parameter
-	const [parentId, parentIdErr] = $.type(ID).optional().nullable().get(params.parentId);
+	const [parentId, parentIdErr] = $.type(ID).optional.nullable.get(params.parentId);
 	if (parentIdErr) return rej('invalid parentId param');
 	if (parentId !== undefined) {
 		if (parentId === null) {
diff --git a/src/server/api/endpoints/drive/stream.ts b/src/server/api/endpoints/drive/stream.ts
index 515f74645ae8a5e9c33d556c4d947df8bf5565fe..612d922c6b8e47ed84b1429a31e5206ea19db680 100644
--- a/src/server/api/endpoints/drive/stream.ts
+++ b/src/server/api/endpoints/drive/stream.ts
@@ -7,15 +7,15 @@ import { ILocalUser } from '../../../../models/user';
  */
 module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Check if both of sinceId and untilId is specified
@@ -24,7 +24,7 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej)
 	}
 
 	// Get 'type' parameter
-	const [type, typeErr] = $.str.optional().match(/^[a-zA-Z\/\-\*]+$/).get(params.type);
+	const [type, typeErr] = $.str.optional.match(/^[a-zA-Z\/\-\*]+$/).get(params.type);
 	if (typeErr) return rej('invalid type param');
 
 	// Construct query
diff --git a/src/server/api/endpoints/i/authorized_apps.ts b/src/server/api/endpoints/i/authorized_apps.ts
index cfc93c1518d8642f86b4758fb633cfece7fd4a3f..9c518b3c84ad890f2635416d3e04391639d5c660 100644
--- a/src/server/api/endpoints/i/authorized_apps.ts
+++ b/src/server/api/endpoints/i/authorized_apps.ts
@@ -8,15 +8,15 @@ import { ILocalUser } from '../../../../models/user';
  */
 module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'offset' parameter
-	const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset);
+	const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset);
 	if (offsetErr) return rej('invalid offset param');
 
 	// Get 'sort' parameter
-	const [sort = 'desc', sortError] = $.str.optional().or('desc asc').get(params.sort);
+	const [sort = 'desc', sortError] = $.str.optional.or('desc asc').get(params.sort);
 	if (sortError) return rej('invalid sort param');
 
 	// Get tokens
diff --git a/src/server/api/endpoints/i/favorites.ts b/src/server/api/endpoints/i/favorites.ts
index dc343afaed17062089d383c0ca7ac3f6cd5dc13e..1ed42a98b13be32bf0163fca51a122829253be81 100644
--- a/src/server/api/endpoints/i/favorites.ts
+++ b/src/server/api/endpoints/i/favorites.ts
@@ -7,15 +7,15 @@ import { ILocalUser } from '../../../../models/user';
  */
 module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Check if both of sinceId and untilId is specified
diff --git a/src/server/api/endpoints/i/notifications.ts b/src/server/api/endpoints/i/notifications.ts
index ce283fe48fc3c8052996107f956f081b06f3b279..93c5abf4d5889c14dd6a1bec0d34fc044885f20f 100644
--- a/src/server/api/endpoints/i/notifications.ts
+++ b/src/server/api/endpoints/i/notifications.ts
@@ -12,27 +12,27 @@ import { ILocalUser } from '../../../../models/user';
 module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'following' parameter
 	const [following = false, followingError] =
-		$.bool.optional().get(params.following);
+		$.bool.optional.get(params.following);
 	if (followingError) return rej('invalid following param');
 
 	// Get 'markAsRead' parameter
-	const [markAsRead = true, markAsReadErr] = $.bool.optional().get(params.markAsRead);
+	const [markAsRead = true, markAsReadErr] = $.bool.optional.get(params.markAsRead);
 	if (markAsReadErr) return rej('invalid markAsRead param');
 
 	// Get 'type' parameter
-	const [type, typeErr] = $.arr($.str).optional().unique().get(params.type);
+	const [type, typeErr] = $.arr($.str).optional.unique().get(params.type);
 	if (typeErr) return rej('invalid type param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Check if both of sinceId and untilId is specified
diff --git a/src/server/api/endpoints/i/signin_history.ts b/src/server/api/endpoints/i/signin_history.ts
index 4ab9881f34539e7b333865fbcab9316a951d7795..e58f48f72db65c1868dcb139534783bc43a39bae 100644
--- a/src/server/api/endpoints/i/signin_history.ts
+++ b/src/server/api/endpoints/i/signin_history.ts
@@ -7,15 +7,15 @@ import { ILocalUser } from '../../../../models/user';
  */
 module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Check if both of sinceId and untilId is specified
diff --git a/src/server/api/endpoints/i/update.ts b/src/server/api/endpoints/i/update.ts
index 57b050ebc42f223e8a459e52ac015d37747710d2..fc23d9fc8258d1a1d05992d7466ddaa7a83892f2 100644
--- a/src/server/api/endpoints/i/update.ts
+++ b/src/server/api/endpoints/i/update.ts
@@ -14,57 +14,57 @@ module.exports = async (params: any, user: ILocalUser, app: IApp) => new Promise
 	const updates = {} as any;
 
 	// Get 'name' parameter
-	const [name, nameErr] = $.str.optional().nullable().pipe(isValidName).get(params.name);
+	const [name, nameErr] = $.str.optional.nullable.pipe(isValidName).get(params.name);
 	if (nameErr) return rej('invalid name param');
 	if (name) updates.name = name;
 
 	// Get 'description' parameter
-	const [description, descriptionErr] = $.str.optional().nullable().pipe(isValidDescription).get(params.description);
+	const [description, descriptionErr] = $.str.optional.nullable.pipe(isValidDescription).get(params.description);
 	if (descriptionErr) return rej('invalid description param');
 	if (description !== undefined) updates.description = description;
 
 	// Get 'location' parameter
-	const [location, locationErr] = $.str.optional().nullable().pipe(isValidLocation).get(params.location);
+	const [location, locationErr] = $.str.optional.nullable.pipe(isValidLocation).get(params.location);
 	if (locationErr) return rej('invalid location param');
 	if (location !== undefined) updates['profile.location'] = location;
 
 	// Get 'birthday' parameter
-	const [birthday, birthdayErr] = $.str.optional().nullable().pipe(isValidBirthday).get(params.birthday);
+	const [birthday, birthdayErr] = $.str.optional.nullable.pipe(isValidBirthday).get(params.birthday);
 	if (birthdayErr) return rej('invalid birthday param');
 	if (birthday !== undefined) updates['profile.birthday'] = birthday;
 
 	// Get 'avatarId' parameter
-	const [avatarId, avatarIdErr] = $.type(ID).optional().nullable().get(params.avatarId);
+	const [avatarId, avatarIdErr] = $.type(ID).optional.nullable.get(params.avatarId);
 	if (avatarIdErr) return rej('invalid avatarId param');
 	if (avatarId !== undefined) updates.avatarId = avatarId;
 
 	// Get 'bannerId' parameter
-	const [bannerId, bannerIdErr] = $.type(ID).optional().nullable().get(params.bannerId);
+	const [bannerId, bannerIdErr] = $.type(ID).optional.nullable.get(params.bannerId);
 	if (bannerIdErr) return rej('invalid bannerId param');
 	if (bannerId !== undefined) updates.bannerId = bannerId;
 
 	// Get 'wallpaperId' parameter
-	const [wallpaperId, wallpaperIdErr] = $.type(ID).optional().nullable().get(params.wallpaperId);
+	const [wallpaperId, wallpaperIdErr] = $.type(ID).optional.nullable.get(params.wallpaperId);
 	if (wallpaperIdErr) return rej('invalid wallpaperId param');
 	if (wallpaperId !== undefined) updates.wallpaperId = wallpaperId;
 
 	// Get 'isLocked' parameter
-	const [isLocked, isLockedErr] = $.bool.optional().get(params.isLocked);
+	const [isLocked, isLockedErr] = $.bool.optional.get(params.isLocked);
 	if (isLockedErr) return rej('invalid isLocked param');
 	if (isLocked != null) updates.isLocked = isLocked;
 
 	// Get 'isBot' parameter
-	const [isBot, isBotErr] = $.bool.optional().get(params.isBot);
+	const [isBot, isBotErr] = $.bool.optional.get(params.isBot);
 	if (isBotErr) return rej('invalid isBot param');
 	if (isBot != null) updates.isBot = isBot;
 
 	// Get 'isCat' parameter
-	const [isCat, isCatErr] = $.bool.optional().get(params.isCat);
+	const [isCat, isCatErr] = $.bool.optional.get(params.isCat);
 	if (isCatErr) return rej('invalid isCat param');
 	if (isCat != null) updates.isCat = isCat;
 
 	// Get 'autoWatch' parameter
-	const [autoWatch, autoWatchErr] = $.bool.optional().get(params.autoWatch);
+	const [autoWatch, autoWatchErr] = $.bool.optional.get(params.autoWatch);
 	if (autoWatchErr) return rej('invalid autoWatch param');
 	if (autoWatch != null) updates['settings.autoWatch'] = autoWatch;
 
diff --git a/src/server/api/endpoints/i/update_client_setting.ts b/src/server/api/endpoints/i/update_client_setting.ts
index 6d6e8ed24ae76fe976bd747c487a0a9c8dcd0c73..9eca66cfcc4e9e0add2d4b3e0967128e82274ac9 100644
--- a/src/server/api/endpoints/i/update_client_setting.ts
+++ b/src/server/api/endpoints/i/update_client_setting.ts
@@ -11,7 +11,7 @@ module.exports = async (params: any, user: ILocalUser) => new Promise(async (res
 	if (nameErr) return rej('invalid name param');
 
 	// Get 'value' parameter
-	const [value, valueErr] = $.any.nullable().get(params.value);
+	const [value, valueErr] = $.any.nullable.get(params.value);
 	if (valueErr) return rej('invalid value param');
 
 	const x: any = {};
diff --git a/src/server/api/endpoints/messaging/history.ts b/src/server/api/endpoints/messaging/history.ts
index 713ba9dd7fff21abb625ec789728012cabc77171..d76aa78230e8aae5a7dfe565e793fd2465f54c42 100644
--- a/src/server/api/endpoints/messaging/history.ts
+++ b/src/server/api/endpoints/messaging/history.ts
@@ -9,7 +9,7 @@ import { ILocalUser } from '../../../../models/user';
  */
 module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	const mute = await Mute.find({
diff --git a/src/server/api/endpoints/messaging/messages.ts b/src/server/api/endpoints/messaging/messages.ts
index 3eb20ec06ba0d7aef26573fc942b84668c8c5258..16236136d371a4676e914ba5f29dfef5f4f18d4f 100644
--- a/src/server/api/endpoints/messaging/messages.ts
+++ b/src/server/api/endpoints/messaging/messages.ts
@@ -26,19 +26,19 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej)
 	}
 
 	// Get 'markAsRead' parameter
-	const [markAsRead = true, markAsReadErr] = $.bool.optional().get(params.markAsRead);
+	const [markAsRead = true, markAsReadErr] = $.bool.optional.get(params.markAsRead);
 	if (markAsReadErr) return rej('invalid markAsRead param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Check if both of sinceId and untilId is specified
diff --git a/src/server/api/endpoints/messaging/messages/create.ts b/src/server/api/endpoints/messaging/messages/create.ts
index b3e4f6a8cdd1e008a6a93155ea7594dfafbecea0..d4f16d0dce854cd2ebf50316cd61e4817c457b68 100644
--- a/src/server/api/endpoints/messaging/messages/create.ts
+++ b/src/server/api/endpoints/messaging/messages/create.ts
@@ -38,11 +38,11 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej)
 	}
 
 	// Get 'text' parameter
-	const [text, textErr] = $.str.optional().pipe(isValidText).get(params.text);
+	const [text, textErr] = $.str.optional.pipe(isValidText).get(params.text);
 	if (textErr) return rej('invalid text');
 
 	// Get 'fileId' parameter
-	const [fileId, fileIdErr] = $.type(ID).optional().get(params.fileId);
+	const [fileId, fileIdErr] = $.type(ID).optional.get(params.fileId);
 	if (fileIdErr) return rej('invalid fileId param');
 
 	let file = null;
diff --git a/src/server/api/endpoints/mute/list.ts b/src/server/api/endpoints/mute/list.ts
index 8b0171be33cfa7d0d9816af6bd0c54706f10db61..b632b1a1a9852ae604235f1b0347ce3969ce0b23 100644
--- a/src/server/api/endpoints/mute/list.ts
+++ b/src/server/api/endpoints/mute/list.ts
@@ -8,15 +8,15 @@ import { getFriendIds } from '../../common/get-friends';
  */
 module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'iknow' parameter
-	const [iknow = false, iknowErr] = $.bool.optional().get(params.iknow);
+	const [iknow = false, iknowErr] = $.bool.optional.get(params.iknow);
 	if (iknowErr) return rej('invalid iknow param');
 
 	// Get 'limit' parameter
-	const [limit = 30, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 30, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'cursor' parameter
-	const [cursor = null, cursorErr] = $.type(ID).optional().get(params.cursor);
+	const [cursor = null, cursorErr] = $.type(ID).optional.get(params.cursor);
 	if (cursorErr) return rej('invalid cursor param');
 
 	// Construct query
diff --git a/src/server/api/endpoints/my/apps.ts b/src/server/api/endpoints/my/apps.ts
index 7687afd0c70ed56803667ab458dd0dd96a1aca76..8f67af88549d7ac855cd1462cddd97f6d93aa969 100644
--- a/src/server/api/endpoints/my/apps.ts
+++ b/src/server/api/endpoints/my/apps.ts
@@ -7,11 +7,11 @@ import { ILocalUser } from '../../../../models/user';
  */
 module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'offset' parameter
-	const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset);
+	const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset);
 	if (offsetErr) return rej('invalid offset param');
 
 	const query = {
diff --git a/src/server/api/endpoints/notes.ts b/src/server/api/endpoints/notes.ts
index 5554e53aa4f547589723d8a44dae6aaecde50560..8b0c4177fca72a6b9ab1d6f24ca6589f0040c5e0 100644
--- a/src/server/api/endpoints/notes.ts
+++ b/src/server/api/endpoints/notes.ts
@@ -9,39 +9,39 @@ import Note, { pack } from '../../../models/note';
  */
 module.exports = (params: any) => new Promise(async (res, rej) => {
 	// Get 'local' parameter
-	const [local, localErr] = $.bool.optional().get(params.local);
+	const [local, localErr] = $.bool.optional.get(params.local);
 	if (localErr) return rej('invalid local param');
 
 	// Get 'reply' parameter
-	const [reply, replyErr] = $.bool.optional().get(params.reply);
+	const [reply, replyErr] = $.bool.optional.get(params.reply);
 	if (replyErr) return rej('invalid reply param');
 
 	// Get 'renote' parameter
-	const [renote, renoteErr] = $.bool.optional().get(params.renote);
+	const [renote, renoteErr] = $.bool.optional.get(params.renote);
 	if (renoteErr) return rej('invalid renote param');
 
 	// Get 'media' parameter
-	const [media, mediaErr] = $.bool.optional().get(params.media);
+	const [media, mediaErr] = $.bool.optional.get(params.media);
 	if (mediaErr) return rej('invalid media param');
 
 	// Get 'poll' parameter
-	const [poll, pollErr] = $.bool.optional().get(params.poll);
+	const [poll, pollErr] = $.bool.optional.get(params.poll);
 	if (pollErr) return rej('invalid poll param');
 
 	// Get 'bot' parameter
-	//const [bot, botErr] = $.bool.optional().get(params.bot);
+	//const [bot, botErr] = $.bool.optional.get(params.bot);
 	//if (botErr) return rej('invalid bot param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Check if both of sinceId and untilId is specified
diff --git a/src/server/api/endpoints/notes/conversation.ts b/src/server/api/endpoints/notes/conversation.ts
index b2bc6a2e72d74bcc3e381bc6a80aa2ab39936e8d..a8e8c4eeb7599371e7099c7067a929d5cafae3eb 100644
--- a/src/server/api/endpoints/notes/conversation.ts
+++ b/src/server/api/endpoints/notes/conversation.ts
@@ -11,11 +11,11 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej)
 	if (noteIdErr) return rej('invalid noteId param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'offset' parameter
-	const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset);
+	const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset);
 	if (offsetErr) return rej('invalid offset param');
 
 	// Lookup note
diff --git a/src/server/api/endpoints/notes/create.ts b/src/server/api/endpoints/notes/create.ts
index 2bd0b430d858a7c68ebc0f02f1c86e21c9d691c5..043f62cf12b4d471fd8abb6726e8cc2971bf2df7 100644
--- a/src/server/api/endpoints/notes/create.ts
+++ b/src/server/api/endpoints/notes/create.ts
@@ -1,33 +1,83 @@
 import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note, { INote, isValidText, isValidCw, pack } from '../../../../models/note';
 import User, { ILocalUser, IUser } from '../../../../models/user';
-import DriveFile from '../../../../models/drive-file';
+import DriveFile, { IDriveFile } from '../../../../models/drive-file';
 import create from '../../../../services/note/create';
 import { IApp } from '../../../../models/app';
 import getParams from '../../get-params';
 
 export const meta = {
 	params: {
-		visibility: {
-			def: $.str.optional().or(['public', 'home', 'followers', 'specified', 'private']),
+		visibility: $.str.optional.or(['public', 'home', 'followers', 'specified', 'private']).note({
 			default: 'public',
 			desc: {
 				ja: '投稿の公開範囲'
 			}
-		},
-		visibleUserIds: {
-			def: $.arr($.type(ID)).optional().unique().min(1),
+		}),
+
+		visibleUserIds: $.arr($.type(ID)).optional.unique().min(1).note({
 			desc: {
 				ja: '(投稿の公開範囲が specified の場合)投稿を閲覧できるユーザー'
 			}
-		},
-		text: {
-			def: $.str.optional().nullable().pipe(isValidText),
+		}),
+
+		text: $.str.optional.nullable.pipe(isValidText).note({
 			default: null,
 			desc: {
 				ja: '投稿内容'
 			}
-		},
+		}),
+
+		cw: $.str.optional.nullable.pipe(isValidCw).note({
+			desc: {
+				ja: 'コンテンツの警告。このパラメータを指定すると設定したテキストで投稿のコンテンツを隠す事が出来ます。'
+			}
+		}),
+
+		viaMobile: $.bool.optional.note({
+			default: false,
+			desc: {
+				ja: 'モバイルデバイスからの投稿か否か。'
+			}
+		}),
+
+		geo: $.obj({
+			coordinates: $.arr().length(2)
+				.item(0, $.num.range(-180, 180))
+				.item(1, $.num.range(-90, 90)),
+			altitude: $.num.nullable,
+			accuracy: $.num.nullable,
+			altitudeAccuracy: $.num.nullable,
+			heading: $.num.nullable.range(0, 360),
+			speed: $.num.nullable
+		}).optional.nullable.strict().note({
+			desc: {
+				ja: '位置情報'
+			}
+		}),
+
+		mediaIds: $.arr($.type(ID)).optional.unique().range(1, 4).note({
+			desc: {
+				ja: '添付するメディア'
+			}
+		}),
+
+		renoteId: $.type(ID).optional.note({
+			desc: {
+				ja: 'Renote対象'
+			}
+		}),
+
+		poll: $.obj({
+			choices: $.arr($.str)
+				.unique()
+				.range(2, 10)
+				.each(c => c.length > 0 && c.length < 50)
+		}).optional.strict().note({
+			desc: {
+				ja: 'アンケート'
+			}
+		})
 	}
 };
 
@@ -45,45 +95,12 @@ module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async
 		})));
 	}
 
-	// Get 'text' parameter
-	const [text = null, textErr] = $.str.optional().nullable().pipe(isValidText).get(params.text);
-	if (textErr) return rej('invalid text');
-
-	// Get 'cw' parameter
-	const [cw, cwErr] = $.str.optional().nullable().pipe(isValidCw).get(params.cw);
-	if (cwErr) return rej('invalid cw');
-
-	// Get 'viaMobile' parameter
-	const [viaMobile = false, viaMobileErr] = $.bool.optional().get(params.viaMobile);
-	if (viaMobileErr) return rej('invalid viaMobile');
-
-	// Get 'tags' parameter
-	const [tags = [], tagsErr] = $.arr($.str.range(1, 32)).optional().unique().get(params.tags);
-	if (tagsErr) return rej('invalid tags');
-
-	// Get 'geo' parameter
-	const [geo, geoErr] = $.obj.optional().nullable().strict()
-		.have('coordinates', $.arr().length(2)
-			.item(0, $.num.range(-180, 180))
-			.item(1, $.num.range(-90, 90)))
-		.have('altitude', $.num.nullable())
-		.have('accuracy', $.num.nullable())
-		.have('altitudeAccuracy', $.num.nullable())
-		.have('heading', $.num.nullable().range(0, 360))
-		.have('speed', $.num.nullable())
-		.get(params.geo);
-	if (geoErr) return rej('invalid geo');
-
-	// Get 'mediaIds' parameter
-	const [mediaIds, mediaIdsErr] = $.arr($.type(ID)).optional().unique().range(1, 4).get(params.mediaIds);
-	if (mediaIdsErr) return rej('invalid mediaIds');
-
-	let files = [];
-	if (mediaIds !== undefined) {
+	let files: IDriveFile[] = [];
+	if (ps.mediaIds !== undefined) {
 		// Fetch files
 		// forEach だと途中でエラーなどがあっても return できないので
 		// 敢えて for を使っています。
-		for (const mediaId of mediaIds) {
+		for (const mediaId of ps.mediaIds) {
 			// Fetch file
 			// SELECT _id
 			const entity = await DriveFile.findOne({
@@ -101,15 +118,11 @@ module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async
 		files = null;
 	}
 
-	// Get 'renoteId' parameter
-	const [renoteId, renoteIdErr] = $.type(ID).optional().get(params.renoteId);
-	if (renoteIdErr) return rej('invalid renoteId');
-
 	let renote: INote = null;
-	if (renoteId !== undefined) {
+	if (ps.renoteId !== undefined) {
 		// Fetch renote to note
 		renote = await Note.findOne({
-			_id: renoteId
+			_id: ps.renoteId
 		});
 
 		if (renote == null) {
@@ -120,7 +133,7 @@ module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async
 	}
 
 	// Get 'replyId' parameter
-	const [replyId, replyIdErr] = $.type(ID).optional().get(params.replyId);
+	const [replyId, replyIdErr] = $.type(ID).optional.get(params.replyId);
 	if (replyIdErr) return rej('invalid replyId');
 
 	let reply: INote = null;
@@ -140,17 +153,8 @@ module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async
 		}
 	}
 
-	// Get 'poll' parameter
-	const [poll, pollErr] = $.obj.optional().strict()
-		.have('choices', $.arr($.str)
-			.unique()
-			.range(2, 10)
-			.each(c => c.length > 0 && c.length < 50))
-		.get(params.poll);
-	if (pollErr) return rej('invalid poll');
-
-	if (poll) {
-		(poll as any).choices = (poll as any).choices.map((choice: string, i: number) => ({
+	if (ps.poll) {
+		(ps.poll as any).choices = (ps.poll as any).choices.map((choice: string, i: number) => ({
 			id: i, // IDを付与
 			text: choice.trim(),
 			votes: 0
@@ -158,7 +162,7 @@ module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async
 	}
 
 	// テキストが無いかつ添付ファイルが無いかつRenoteも無いかつ投票も無かったらエラー
-	if ((text === undefined || text === null) && files === null && renote === null && poll === undefined) {
+	if ((ps.text === undefined || ps.text === null) && files === null && renote === null && ps.poll === undefined) {
 		return rej('text, mediaIds, renoteId or poll is required');
 	}
 
@@ -166,17 +170,16 @@ module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async
 	const note = await create(user, {
 		createdAt: new Date(),
 		media: files,
-		poll,
-		text,
+		poll: ps.poll,
+		text: ps.text,
 		reply,
 		renote,
-		cw,
-		tags,
+		cw: ps.cw,
 		app,
-		viaMobile,
-		visibility,
+		viaMobile: ps.viaMobile,
+		visibility: ps.visibility,
 		visibleUsers,
-		geo
+		geo: ps.geo
 	});
 
 	const noteObj = await pack(note, user);
diff --git a/src/server/api/endpoints/notes/global-timeline.ts b/src/server/api/endpoints/notes/global-timeline.ts
index 24ffdbcba7993edded6f5f132c09120fd0ea0602..d032aa1a624ecfa44e327fa3fc756112dd667ae0 100644
--- a/src/server/api/endpoints/notes/global-timeline.ts
+++ b/src/server/api/endpoints/notes/global-timeline.ts
@@ -9,23 +9,23 @@ import { ILocalUser } from '../../../../models/user';
  */
 module.exports = async (params: any, user: ILocalUser) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) throw 'invalid limit param';
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) throw 'invalid sinceId param';
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) throw 'invalid untilId param';
 
 	// Get 'sinceDate' parameter
-	const [sinceDate, sinceDateErr] = $.num.optional().get(params.sinceDate);
+	const [sinceDate, sinceDateErr] = $.num.optional.get(params.sinceDate);
 	if (sinceDateErr) throw 'invalid sinceDate param';
 
 	// Get 'untilDate' parameter
-	const [untilDate, untilDateErr] = $.num.optional().get(params.untilDate);
+	const [untilDate, untilDateErr] = $.num.optional.get(params.untilDate);
 	if (untilDateErr) throw 'invalid untilDate param';
 
 	// Check if only one of sinceId, untilId, sinceDate, untilDate specified
@@ -34,7 +34,7 @@ module.exports = async (params: any, user: ILocalUser) => {
 	}
 
 	// Get 'mediaOnly' parameter
-	const [mediaOnly, mediaOnlyErr] = $.bool.optional().get(params.mediaOnly);
+	const [mediaOnly, mediaOnlyErr] = $.bool.optional.get(params.mediaOnly);
 	if (mediaOnlyErr) throw 'invalid mediaOnly param';
 
 	// ミュートしているユーザーを取得
diff --git a/src/server/api/endpoints/notes/local-timeline.ts b/src/server/api/endpoints/notes/local-timeline.ts
index 48490638d2ecba159df69828a5c4f6fc2c1d6ffc..74462ce4e4bade0cd2cbbab99285d5a50f0bebc3 100644
--- a/src/server/api/endpoints/notes/local-timeline.ts
+++ b/src/server/api/endpoints/notes/local-timeline.ts
@@ -9,23 +9,23 @@ import { ILocalUser } from '../../../../models/user';
  */
 module.exports = async (params: any, user: ILocalUser) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) throw 'invalid limit param';
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) throw 'invalid sinceId param';
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) throw 'invalid untilId param';
 
 	// Get 'sinceDate' parameter
-	const [sinceDate, sinceDateErr] = $.num.optional().get(params.sinceDate);
+	const [sinceDate, sinceDateErr] = $.num.optional.get(params.sinceDate);
 	if (sinceDateErr) throw 'invalid sinceDate param';
 
 	// Get 'untilDate' parameter
-	const [untilDate, untilDateErr] = $.num.optional().get(params.untilDate);
+	const [untilDate, untilDateErr] = $.num.optional.get(params.untilDate);
 	if (untilDateErr) throw 'invalid untilDate param';
 
 	// Check if only one of sinceId, untilId, sinceDate, untilDate specified
@@ -34,7 +34,7 @@ module.exports = async (params: any, user: ILocalUser) => {
 	}
 
 	// Get 'mediaOnly' parameter
-	const [mediaOnly, mediaOnlyErr] = $.bool.optional().get(params.mediaOnly);
+	const [mediaOnly, mediaOnlyErr] = $.bool.optional.get(params.mediaOnly);
 	if (mediaOnlyErr) throw 'invalid mediaOnly param';
 
 	// ミュートしているユーザーを取得
diff --git a/src/server/api/endpoints/notes/mentions.ts b/src/server/api/endpoints/notes/mentions.ts
index 45511603afcf0ac7126650b382bb363016b3e7bd..06ddc258b006b18b56db692a5758454a67887214 100644
--- a/src/server/api/endpoints/notes/mentions.ts
+++ b/src/server/api/endpoints/notes/mentions.ts
@@ -10,19 +10,19 @@ import { ILocalUser } from '../../../../models/user';
 module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'following' parameter
 	const [following = false, followingError] =
-		$.bool.optional().get(params.following);
+		$.bool.optional.get(params.following);
 	if (followingError) return rej('invalid following param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Check if both of sinceId and untilId is specified
diff --git a/src/server/api/endpoints/notes/polls/recommendation.ts b/src/server/api/endpoints/notes/polls/recommendation.ts
index 640140c3d1959679bd51c299d97d529104482ee6..fb1ee6dda8a25cc02ee0390c6a7925dcea571fb5 100644
--- a/src/server/api/endpoints/notes/polls/recommendation.ts
+++ b/src/server/api/endpoints/notes/polls/recommendation.ts
@@ -8,11 +8,11 @@ import { ILocalUser } from '../../../../../models/user';
  */
 module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'offset' parameter
-	const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset);
+	const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset);
 	if (offsetErr) return rej('invalid offset param');
 
 	// Get votes
diff --git a/src/server/api/endpoints/notes/reactions.ts b/src/server/api/endpoints/notes/reactions.ts
index d3b2d4343201dc12d36a775dc3c9946a4a6a1e1d..cf88f3860a55a30cbfda22cbe7a9d9a7794ddc4e 100644
--- a/src/server/api/endpoints/notes/reactions.ts
+++ b/src/server/api/endpoints/notes/reactions.ts
@@ -12,15 +12,15 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej)
 	if (noteIdErr) return rej('invalid noteId param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'offset' parameter
-	const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset);
+	const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset);
 	if (offsetErr) return rej('invalid offset param');
 
 	// Get 'sort' parameter
-	const [sort = 'desc', sortError] = $.str.optional().or('desc asc').get(params.sort);
+	const [sort = 'desc', sortError] = $.str.optional.or('desc asc').get(params.sort);
 	if (sortError) return rej('invalid sort param');
 
 	// Lookup note
diff --git a/src/server/api/endpoints/notes/replies.ts b/src/server/api/endpoints/notes/replies.ts
index 4aaf1d322b5e82324638a5de48da6ebe14b8bfe2..3b209b317669a7f8af4159ef4dfcdb8d019df329 100644
--- a/src/server/api/endpoints/notes/replies.ts
+++ b/src/server/api/endpoints/notes/replies.ts
@@ -11,11 +11,11 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej)
 	if (noteIdErr) return rej('invalid noteId param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'offset' parameter
-	const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset);
+	const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset);
 	if (offsetErr) return rej('invalid offset param');
 
 	// Lookup note
diff --git a/src/server/api/endpoints/notes/reposts.ts b/src/server/api/endpoints/notes/reposts.ts
index ea3f174e1a2ae67ee862597f75a26301e413509d..043a653e8319beffe40f4b6a5c654284b7f20dd4 100644
--- a/src/server/api/endpoints/notes/reposts.ts
+++ b/src/server/api/endpoints/notes/reposts.ts
@@ -11,15 +11,15 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej)
 	if (noteIdErr) return rej('invalid noteId param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Check if both of sinceId and untilId is specified
diff --git a/src/server/api/endpoints/notes/search.ts b/src/server/api/endpoints/notes/search.ts
index 20c628b84dcdabb72aa007c4b7be7961f43893fe..3dbf407dffd132864ae20c57c167e3db027e38db 100644
--- a/src/server/api/endpoints/notes/search.ts
+++ b/src/server/api/endpoints/notes/search.ts
@@ -11,11 +11,11 @@ module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) =
 	if (queryError) return rej('invalid query param');
 
 	// Get 'offset' parameter
-	const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset);
+	const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset);
 	if (offsetErr) return rej('invalid offset param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 30).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 30).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	es.search({
diff --git a/src/server/api/endpoints/notes/search_by_tag.ts b/src/server/api/endpoints/notes/search_by_tag.ts
index 9be7cfffb698375974312155f1e6269511a3d383..78487e2c03fbfbe4bcfb8542ab12f52d9da7c82b 100644
--- a/src/server/api/endpoints/notes/search_by_tag.ts
+++ b/src/server/api/endpoints/notes/search_by_tag.ts
@@ -14,59 +14,59 @@ module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) =
 	if (tagError) return rej('invalid tag param');
 
 	// Get 'includeUserIds' parameter
-	const [includeUserIds = [], includeUserIdsErr] = $.arr($.type(ID)).optional().get(params.includeUserIds);
+	const [includeUserIds = [], includeUserIdsErr] = $.arr($.type(ID)).optional.get(params.includeUserIds);
 	if (includeUserIdsErr) return rej('invalid includeUserIds param');
 
 	// Get 'excludeUserIds' parameter
-	const [excludeUserIds = [], excludeUserIdsErr] = $.arr($.type(ID)).optional().get(params.excludeUserIds);
+	const [excludeUserIds = [], excludeUserIdsErr] = $.arr($.type(ID)).optional.get(params.excludeUserIds);
 	if (excludeUserIdsErr) return rej('invalid excludeUserIds param');
 
 	// Get 'includeUserUsernames' parameter
-	const [includeUserUsernames = [], includeUserUsernamesErr] = $.arr($.str).optional().get(params.includeUserUsernames);
+	const [includeUserUsernames = [], includeUserUsernamesErr] = $.arr($.str).optional.get(params.includeUserUsernames);
 	if (includeUserUsernamesErr) return rej('invalid includeUserUsernames param');
 
 	// Get 'excludeUserUsernames' parameter
-	const [excludeUserUsernames = [], excludeUserUsernamesErr] = $.arr($.str).optional().get(params.excludeUserUsernames);
+	const [excludeUserUsernames = [], excludeUserUsernamesErr] = $.arr($.str).optional.get(params.excludeUserUsernames);
 	if (excludeUserUsernamesErr) return rej('invalid excludeUserUsernames param');
 
 	// Get 'following' parameter
-	const [following = null, followingErr] = $.bool.optional().nullable().get(params.following);
+	const [following = null, followingErr] = $.bool.optional.nullable.get(params.following);
 	if (followingErr) return rej('invalid following param');
 
 	// Get 'mute' parameter
-	const [mute = 'mute_all', muteErr] = $.str.optional().get(params.mute);
+	const [mute = 'mute_all', muteErr] = $.str.optional.get(params.mute);
 	if (muteErr) return rej('invalid mute param');
 
 	// Get 'reply' parameter
-	const [reply = null, replyErr] = $.bool.optional().nullable().get(params.reply);
+	const [reply = null, replyErr] = $.bool.optional.nullable.get(params.reply);
 	if (replyErr) return rej('invalid reply param');
 
 	// Get 'renote' parameter
-	const [renote = null, renoteErr] = $.bool.optional().nullable().get(params.renote);
+	const [renote = null, renoteErr] = $.bool.optional.nullable.get(params.renote);
 	if (renoteErr) return rej('invalid renote param');
 
 	// Get 'media' parameter
-	const [media = null, mediaErr] = $.bool.optional().nullable().get(params.media);
+	const [media = null, mediaErr] = $.bool.optional.nullable.get(params.media);
 	if (mediaErr) return rej('invalid media param');
 
 	// Get 'poll' parameter
-	const [poll = null, pollErr] = $.bool.optional().nullable().get(params.poll);
+	const [poll = null, pollErr] = $.bool.optional.nullable.get(params.poll);
 	if (pollErr) return rej('invalid poll param');
 
 	// Get 'sinceDate' parameter
-	const [sinceDate, sinceDateErr] = $.num.optional().get(params.sinceDate);
+	const [sinceDate, sinceDateErr] = $.num.optional.get(params.sinceDate);
 	if (sinceDateErr) throw 'invalid sinceDate param';
 
 	// Get 'untilDate' parameter
-	const [untilDate, untilDateErr] = $.num.optional().get(params.untilDate);
+	const [untilDate, untilDateErr] = $.num.optional.get(params.untilDate);
 	if (untilDateErr) throw 'invalid untilDate param';
 
 	// Get 'offset' parameter
-	const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset);
+	const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset);
 	if (offsetErr) return rej('invalid offset param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 30).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 30).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	if (includeUserUsernames != null) {
diff --git a/src/server/api/endpoints/notes/timeline.ts b/src/server/api/endpoints/notes/timeline.ts
index 18c0acd37982e1178f17358f9a19923776bfb8cb..9a5306be619a107254766b52867c7fdfd7a4ccd1 100644
--- a/src/server/api/endpoints/notes/timeline.ts
+++ b/src/server/api/endpoints/notes/timeline.ts
@@ -10,23 +10,23 @@ import { ILocalUser } from '../../../../models/user';
  */
 module.exports = async (params: any, user: ILocalUser) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) throw 'invalid limit param';
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) throw 'invalid sinceId param';
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) throw 'invalid untilId param';
 
 	// Get 'sinceDate' parameter
-	const [sinceDate, sinceDateErr] = $.num.optional().get(params.sinceDate);
+	const [sinceDate, sinceDateErr] = $.num.optional.get(params.sinceDate);
 	if (sinceDateErr) throw 'invalid sinceDate param';
 
 	// Get 'untilDate' parameter
-	const [untilDate, untilDateErr] = $.num.optional().get(params.untilDate);
+	const [untilDate, untilDateErr] = $.num.optional.get(params.untilDate);
 	if (untilDateErr) throw 'invalid untilDate param';
 
 	// Check if only one of sinceId, untilId, sinceDate, untilDate specified
@@ -35,15 +35,15 @@ module.exports = async (params: any, user: ILocalUser) => {
 	}
 
 	// Get 'includeMyRenotes' parameter
-	const [includeMyRenotes = true, includeMyRenotesErr] = $.bool.optional().get(params.includeMyRenotes);
+	const [includeMyRenotes = true, includeMyRenotesErr] = $.bool.optional.get(params.includeMyRenotes);
 	if (includeMyRenotesErr) throw 'invalid includeMyRenotes param';
 
 	// Get 'includeRenotedMyNotes' parameter
-	const [includeRenotedMyNotes = true, includeRenotedMyNotesErr] = $.bool.optional().get(params.includeRenotedMyNotes);
+	const [includeRenotedMyNotes = true, includeRenotedMyNotesErr] = $.bool.optional.get(params.includeRenotedMyNotes);
 	if (includeRenotedMyNotesErr) throw 'invalid includeRenotedMyNotes param';
 
 	// Get 'mediaOnly' parameter
-	const [mediaOnly, mediaOnlyErr] = $.bool.optional().get(params.mediaOnly);
+	const [mediaOnly, mediaOnlyErr] = $.bool.optional.get(params.mediaOnly);
 	if (mediaOnlyErr) throw 'invalid mediaOnly param';
 
 	const [followings, mutedUserIds] = await Promise.all([
diff --git a/src/server/api/endpoints/notes/trend.ts b/src/server/api/endpoints/notes/trend.ts
index 9c0a1bb1124e2b38c7a7b4d753146e6d2f0379b5..b4acd7c5f4d0394f355cdabdb3e0e14aa75742c6 100644
--- a/src/server/api/endpoints/notes/trend.ts
+++ b/src/server/api/endpoints/notes/trend.ts
@@ -8,27 +8,27 @@ import { ILocalUser } from '../../../../models/user';
  */
 module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'offset' parameter
-	const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset);
+	const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset);
 	if (offsetErr) return rej('invalid offset param');
 
 	// Get 'reply' parameter
-	const [reply, replyErr] = $.bool.optional().get(params.reply);
+	const [reply, replyErr] = $.bool.optional.get(params.reply);
 	if (replyErr) return rej('invalid reply param');
 
 	// Get 'renote' parameter
-	const [renote, renoteErr] = $.bool.optional().get(params.renote);
+	const [renote, renoteErr] = $.bool.optional.get(params.renote);
 	if (renoteErr) return rej('invalid renote param');
 
 	// Get 'media' parameter
-	const [media, mediaErr] = $.bool.optional().get(params.media);
+	const [media, mediaErr] = $.bool.optional.get(params.media);
 	if (mediaErr) return rej('invalid media param');
 
 	// Get 'poll' parameter
-	const [poll, pollErr] = $.bool.optional().get(params.poll);
+	const [poll, pollErr] = $.bool.optional.get(params.poll);
 	if (pollErr) return rej('invalid poll param');
 
 	const query = {
diff --git a/src/server/api/endpoints/notes/user-list-timeline.ts b/src/server/api/endpoints/notes/user-list-timeline.ts
index 8aa800b712e9850b997f814e05cb540f4f6a82fb..f14a869c7fc0d20d11a703a973d38ab9095a332a 100644
--- a/src/server/api/endpoints/notes/user-list-timeline.ts
+++ b/src/server/api/endpoints/notes/user-list-timeline.ts
@@ -10,23 +10,23 @@ import { ILocalUser } from '../../../../models/user';
  */
 module.exports = async (params: any, user: ILocalUser) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) throw 'invalid limit param';
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) throw 'invalid sinceId param';
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) throw 'invalid untilId param';
 
 	// Get 'sinceDate' parameter
-	const [sinceDate, sinceDateErr] = $.num.optional().get(params.sinceDate);
+	const [sinceDate, sinceDateErr] = $.num.optional.get(params.sinceDate);
 	if (sinceDateErr) throw 'invalid sinceDate param';
 
 	// Get 'untilDate' parameter
-	const [untilDate, untilDateErr] = $.num.optional().get(params.untilDate);
+	const [untilDate, untilDateErr] = $.num.optional.get(params.untilDate);
 	if (untilDateErr) throw 'invalid untilDate param';
 
 	// Check if only one of sinceId, untilId, sinceDate, untilDate specified
@@ -35,15 +35,15 @@ module.exports = async (params: any, user: ILocalUser) => {
 	}
 
 	// Get 'includeMyRenotes' parameter
-	const [includeMyRenotes = true, includeMyRenotesErr] = $.bool.optional().get(params.includeMyRenotes);
+	const [includeMyRenotes = true, includeMyRenotesErr] = $.bool.optional.get(params.includeMyRenotes);
 	if (includeMyRenotesErr) throw 'invalid includeMyRenotes param';
 
 	// Get 'includeRenotedMyNotes' parameter
-	const [includeRenotedMyNotes = true, includeRenotedMyNotesErr] = $.bool.optional().get(params.includeRenotedMyNotes);
+	const [includeRenotedMyNotes = true, includeRenotedMyNotesErr] = $.bool.optional.get(params.includeRenotedMyNotes);
 	if (includeRenotedMyNotesErr) throw 'invalid includeRenotedMyNotes param';
 
 	// Get 'mediaOnly' parameter
-	const [mediaOnly, mediaOnlyErr] = $.bool.optional().get(params.mediaOnly);
+	const [mediaOnly, mediaOnlyErr] = $.bool.optional.get(params.mediaOnly);
 	if (mediaOnlyErr) throw 'invalid mediaOnly param';
 
 	// Get 'listId' parameter
diff --git a/src/server/api/endpoints/reversi/games.ts b/src/server/api/endpoints/reversi/games.ts
index 1455f191f7b406e6d29ca9d0f549946d7c04ae94..e68f57c6d41a4ca9535f19601fa5fb1f7506dea3 100644
--- a/src/server/api/endpoints/reversi/games.ts
+++ b/src/server/api/endpoints/reversi/games.ts
@@ -4,19 +4,19 @@ import { ILocalUser } from '../../../../models/user';
 
 module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'my' parameter
-	const [my = false, myErr] = $.bool.optional().get(params.my);
+	const [my = false, myErr] = $.bool.optional.get(params.my);
 	if (myErr) return rej('invalid my param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Check if both of sinceId and untilId is specified
diff --git a/src/server/api/endpoints/users.ts b/src/server/api/endpoints/users.ts
index b8df6f3ecf5db30143aa10fd5a0becec059cb2a9..0756ddc9180061123a6f751d21d0c65b152e18e8 100644
--- a/src/server/api/endpoints/users.ts
+++ b/src/server/api/endpoints/users.ts
@@ -6,15 +6,15 @@ import User, { pack, ILocalUser } from '../../../models/user';
  */
 module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'offset' parameter
-	const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset);
+	const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset);
 	if (offsetErr) return rej('invalid offset param');
 
 	// Get 'sort' parameter
-	const [sort, sortError] = $.str.optional().or('+follower|-follower').get(params.sort);
+	const [sort, sortError] = $.str.optional.or('+follower|-follower').get(params.sort);
 	if (sortError) return rej('invalid sort param');
 
 	// Construct query
diff --git a/src/server/api/endpoints/users/followers.ts b/src/server/api/endpoints/users/followers.ts
index 53133ee96979b9e98dc6d39743fd3aa2c7bbb096..ef36a0df46c6555b8125584e93393e4b5be4a549 100644
--- a/src/server/api/endpoints/users/followers.ts
+++ b/src/server/api/endpoints/users/followers.ts
@@ -13,15 +13,15 @@ module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) =
 	if (userIdErr) return rej('invalid userId param');
 
 	// Get 'iknow' parameter
-	const [iknow = false, iknowErr] = $.bool.optional().get(params.iknow);
+	const [iknow = false, iknowErr] = $.bool.optional.get(params.iknow);
 	if (iknowErr) return rej('invalid iknow param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'cursor' parameter
-	const [cursor = null, cursorErr] = $.type(ID).optional().get(params.cursor);
+	const [cursor = null, cursorErr] = $.type(ID).optional.get(params.cursor);
 	if (cursorErr) return rej('invalid cursor param');
 
 	// Lookup user
diff --git a/src/server/api/endpoints/users/following.ts b/src/server/api/endpoints/users/following.ts
index 206120019834bd6533d001793f9f194dfc364760..2c38fe4f8767f07d668906260c5d5f04e562e9e2 100644
--- a/src/server/api/endpoints/users/following.ts
+++ b/src/server/api/endpoints/users/following.ts
@@ -13,15 +13,15 @@ module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) =
 	if (userIdErr) return rej('invalid userId param');
 
 	// Get 'iknow' parameter
-	const [iknow = false, iknowErr] = $.bool.optional().get(params.iknow);
+	const [iknow = false, iknowErr] = $.bool.optional.get(params.iknow);
 	if (iknowErr) return rej('invalid iknow param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'cursor' parameter
-	const [cursor = null, cursorErr] = $.type(ID).optional().get(params.cursor);
+	const [cursor = null, cursorErr] = $.type(ID).optional.get(params.cursor);
 	if (cursorErr) return rej('invalid cursor param');
 
 	// Lookup user
diff --git a/src/server/api/endpoints/users/get_frequently_replied_users.ts b/src/server/api/endpoints/users/get_frequently_replied_users.ts
index ba8779d3343b1a9cdb8a7587d7c6e0683cb0230d..6077420908bcda8bf76f0fe01e3c8eaaeaff3e82 100644
--- a/src/server/api/endpoints/users/get_frequently_replied_users.ts
+++ b/src/server/api/endpoints/users/get_frequently_replied_users.ts
@@ -8,7 +8,7 @@ module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) =
 	if (userIdErr) return rej('invalid userId param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Lookup user
diff --git a/src/server/api/endpoints/users/notes.ts b/src/server/api/endpoints/users/notes.ts
index 222a8d950a27c89eea7de61c4b0c995b8d53012b..ac4e17946a623893ef3dc768938f346b52b1ad46 100644
--- a/src/server/api/endpoints/users/notes.ts
+++ b/src/server/api/endpoints/users/notes.ts
@@ -8,11 +8,11 @@ import User, { ILocalUser } from '../../../../models/user';
  */
 module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
-	const [userId, userIdErr] = $.type(ID).optional().get(params.userId);
+	const [userId, userIdErr] = $.type(ID).optional.get(params.userId);
 	if (userIdErr) return rej('invalid userId param');
 
 	// Get 'username' parameter
-	const [username, usernameErr] = $.str.optional().get(params.username);
+	const [username, usernameErr] = $.str.optional.get(params.username);
 	if (usernameErr) return rej('invalid username param');
 
 	if (userId === undefined && username === undefined) {
@@ -20,7 +20,7 @@ module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) =
 	}
 
 	// Get 'host' parameter
-	const [host, hostErr] = $.str.optional().get(params.host);
+	const [host, hostErr] = $.str.optional.get(params.host);
 	if (hostErr) return rej('invalid host param');
 
 	if (userId === undefined && host === undefined) {
@@ -28,31 +28,31 @@ module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) =
 	}
 
 	// Get 'includeReplies' parameter
-	const [includeReplies = true, includeRepliesErr] = $.bool.optional().get(params.includeReplies);
+	const [includeReplies = true, includeRepliesErr] = $.bool.optional.get(params.includeReplies);
 	if (includeRepliesErr) return rej('invalid includeReplies param');
 
 	// Get 'withMedia' parameter
-	const [withMedia = false, withMediaErr] = $.bool.optional().get(params.withMedia);
+	const [withMedia = false, withMediaErr] = $.bool.optional.get(params.withMedia);
 	if (withMediaErr) return rej('invalid withMedia param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Get 'sinceDate' parameter
-	const [sinceDate, sinceDateErr] = $.num.optional().get(params.sinceDate);
+	const [sinceDate, sinceDateErr] = $.num.optional.get(params.sinceDate);
 	if (sinceDateErr) throw 'invalid sinceDate param';
 
 	// Get 'untilDate' parameter
-	const [untilDate, untilDateErr] = $.num.optional().get(params.untilDate);
+	const [untilDate, untilDateErr] = $.num.optional.get(params.untilDate);
 	if (untilDateErr) throw 'invalid untilDate param';
 
 	// Check if only one of sinceId, untilId, sinceDate, untilDate specified
diff --git a/src/server/api/endpoints/users/recommendation.ts b/src/server/api/endpoints/users/recommendation.ts
index 1d0d889f11c347506e0b7eb5df71b3421926e3f9..6221d751b4fe5c4e60f42a67206f0147e59d23eb 100644
--- a/src/server/api/endpoints/users/recommendation.ts
+++ b/src/server/api/endpoints/users/recommendation.ts
@@ -9,11 +9,11 @@ import Mute from '../../../../models/mute';
  */
 module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'offset' parameter
-	const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset);
+	const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset);
 	if (offsetErr) return rej('invalid offset param');
 
 	// ID list of the user itself and other users who the user follows
diff --git a/src/server/api/endpoints/users/search.ts b/src/server/api/endpoints/users/search.ts
index e29c8d32f17095f92f64767c9e9ffc45c1d677a3..36a708d21e8c203c4d7869b7d74c8e250faf54bc 100644
--- a/src/server/api/endpoints/users/search.ts
+++ b/src/server/api/endpoints/users/search.ts
@@ -11,7 +11,7 @@ module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) =
 	if (queryError) return rej('invalid query param');
 
 	// Get 'max' parameter
-	const [max = 10, maxErr] = $.num.optional().range(1, 30).get(params.max);
+	const [max = 10, maxErr] = $.num.optional.range(1, 30).get(params.max);
 	if (maxErr) return rej('invalid max param');
 
 	const escapedQuery = escapeRegexp(query);
diff --git a/src/server/api/endpoints/users/search_by_username.ts b/src/server/api/endpoints/users/search_by_username.ts
index 937f9af58982793e62e41d575a31df6681e9d43b..1c0f09449c28c9de3363240e9d1ec28c01480903 100644
--- a/src/server/api/endpoints/users/search_by_username.ts
+++ b/src/server/api/endpoints/users/search_by_username.ts
@@ -10,11 +10,11 @@ module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) =
 	if (queryError) return rej('invalid query param');
 
 	// Get 'offset' parameter
-	const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset);
+	const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset);
 	if (offsetErr) return rej('invalid offset param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	let users = await User
diff --git a/src/server/api/endpoints/users/show.ts b/src/server/api/endpoints/users/show.ts
index bf7e2a23125b5aefb0e2020df8f9f4a3090c74f8..5cbd83f649e1e999505bda71046a6c8b527dc7f3 100644
--- a/src/server/api/endpoints/users/show.ts
+++ b/src/server/api/endpoints/users/show.ts
@@ -11,19 +11,19 @@ module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) =
 	let user;
 
 	// Get 'userId' parameter
-	const [userId, userIdErr] = $.type(ID).optional().get(params.userId);
+	const [userId, userIdErr] = $.type(ID).optional.get(params.userId);
 	if (userIdErr) return rej('invalid userId param');
 
 	// Get 'userIds' parameter
-	const [userIds, userIdsErr] = $.arr($.type(ID)).optional().get(params.userIds);
+	const [userIds, userIdsErr] = $.arr($.type(ID)).optional.get(params.userIds);
 	if (userIdsErr) return rej('invalid userIds param');
 
 	// Get 'username' parameter
-	const [username, usernameErr] = $.str.optional().get(params.username);
+	const [username, usernameErr] = $.str.optional.get(params.username);
 	if (usernameErr) return rej('invalid username param');
 
 	// Get 'host' parameter
-	const [host, hostErr] = $.str.optional().nullable().get(params.host);
+	const [host, hostErr] = $.str.optional.nullable.get(params.host);
 	if (hostErr) return rej('invalid host param');
 
 	if (userIds) {
diff --git a/src/server/api/get-params.ts b/src/server/api/get-params.ts
index 6b047a28f4bae3118474cd8021fc18f57bda2a18..e495e3ef3e12c7ba52aef0a1bf8e8e1b14f6b048 100644
--- a/src/server/api/get-params.ts
+++ b/src/server/api/get-params.ts
@@ -1,25 +1,22 @@
-import { Query } from 'cafy';
+import { Context } from 'cafy';
 
 type Defs = {
-	params: {[key: string]: {
-		def: Query<any>;
-		default?: any;
-	}}
+	params: { [key: string]: Context<any> }
 };
 
 export default function <T extends Defs>(defs: T, params: any): [{
-	[P in keyof T['params']]: ReturnType<T['params'][P]['def']['get']>[0];
+	[P in keyof T['params']]: ReturnType<T['params'][P]['get']>[0];
 }, Error] {
 	const x: any = {};
 	let err: Error = null;
 	Object.keys(defs.params).some(k => {
-		const [v, e] = defs.params[k].def.get(params[k]);
+		const [v, e] = defs.params[k].get(params[k]);
 		if (e) {
 			err = e;
 			return true;
 		} else {
-			if (v === undefined && defs.params[k].default) {
-				x[k] = defs.params[k].default;
+			if (v === undefined && defs.params[k].data.default) {
+				x[k] = defs.params[k].data.default;
 			} else {
 				x[k] = v;
 			}