diff --git a/package.json b/package.json
index 0a3026e17e802efb897f60e4970b6a1c59fc92d5..ae90d213018bec74aa84894b4ac0341274b92f86 100644
--- a/package.json
+++ b/package.json
@@ -88,7 +88,7 @@
 		"autwh": "0.1.0",
 		"bcryptjs": "2.4.3",
 		"bootstrap-vue": "2.0.0-rc.6",
-		"cafy": "3.2.1",
+		"cafy": "5.1.0",
 		"chai": "4.1.2",
 		"chai-http": "4.0.0",
 		"chalk": "2.4.0",
diff --git a/src/cafy-id.ts b/src/cafy-id.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1109d42d8fdbc8999f291ee9a2e7e1a9a9e51632
--- /dev/null
+++ b/src/cafy-id.ts
@@ -0,0 +1,29 @@
+import * as mongo from 'mongodb';
+import { Query } from 'cafy';
+
+export const isAnId = x => mongo.ObjectID.isValid(x);
+export const isNotAnId = x => !isAnId(x);
+
+/**
+ * ID
+ */
+export default class ID extends Query<mongo.ObjectID> {
+	constructor(...args) {
+		super(...args);
+
+		this.transform = v => {
+			if (isAnId(v) && !mongo.ObjectID.prototype.isPrototypeOf(v)) {
+				return new mongo.ObjectID(v);
+			} else {
+				return v;
+			}
+		};
+
+		this.pushFirstTimeValidator(v => {
+			if (!mongo.ObjectID.prototype.isPrototypeOf(v) && isNotAnId(v)) {
+				return new Error('must-be-an-id');
+			}
+			return true;
+		});
+	}
+}
diff --git a/src/models/note-reaction.ts b/src/models/note-reaction.ts
index 7891ebdf1719b61fb636472d8dba536f37b188fa..f78b0d9d01f6d0aad9d61c31ad8415e232ff24ee 100644
--- a/src/models/note-reaction.ts
+++ b/src/models/note-reaction.ts
@@ -1,5 +1,5 @@
 import * as mongo from 'mongodb';
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import deepcopy = require('deepcopy');
 import db from '../db/mongodb';
 import Reaction from './note-reaction';
diff --git a/src/models/user-list.ts b/src/models/user-list.ts
index 66e2afe213cbabd42bfd678da289ed5ad28f2baf..7100fced7e56b154e1217c803a650b790cc4ab26 100644
--- a/src/models/user-list.ts
+++ b/src/models/user-list.ts
@@ -1,4 +1,5 @@
 import * as mongo from 'mongodb';
+import deepcopy = require('deepcopy');
 import db from '../db/mongodb';
 
 const UserList = db.get<IUserList>('userList');
@@ -38,3 +39,29 @@ export async function deleteUserList(userList: string | mongo.ObjectID | IUserLi
 		_id: u._id
 	});
 }
+
+export const pack = (
+	userList: string | mongo.ObjectID | IUserList
+) => new Promise<any>(async (resolve, reject) => {
+	let _userList: any;
+
+	if (mongo.ObjectID.prototype.isPrototypeOf(userList)) {
+		_userList = await UserList.findOne({
+			_id: userList
+		});
+	} else if (typeof userList === 'string') {
+		_userList = await UserList.findOne({
+			_id: new mongo.ObjectID(userList)
+		});
+	} else {
+		_userList = deepcopy(userList);
+	}
+
+	if (!_userList) throw `invalid userList arg ${userList}`;
+
+	// Rename _id to id
+	_userList.id = _userList._id;
+	delete _userList._id;
+
+	resolve(_userList);
+});
diff --git a/src/server/api/endpoints/aggregation/posts.ts b/src/server/api/endpoints/aggregation/posts.ts
index cc2a48b53de3cc011935b36c57249bb1d6fab831..17bead2808c7527df34a1315dc4dc7f596e35bcb 100644
--- a/src/server/api/endpoints/aggregation/posts.ts
+++ b/src/server/api/endpoints/aggregation/posts.ts
@@ -6,9 +6,6 @@ import Note from '../../../../models/note';
 
 /**
  * Aggregate notes
- *
- * @param {any} params
- * @return {Promise<any>}
  */
 module.exports = params => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
diff --git a/src/server/api/endpoints/aggregation/users.ts b/src/server/api/endpoints/aggregation/users.ts
index 19776ed297d99c97d0b3c355adbced3085a36baf..b0a7632f249e33d00fe9c63812ec2c6cc7b75f9a 100644
--- a/src/server/api/endpoints/aggregation/users.ts
+++ b/src/server/api/endpoints/aggregation/users.ts
@@ -6,9 +6,6 @@ import User from '../../../../models/user';
 
 /**
  * Aggregate users
- *
- * @param {any} params
- * @return {Promise<any>}
  */
 module.exports = params => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
diff --git a/src/server/api/endpoints/aggregation/users/activity.ts b/src/server/api/endpoints/aggregation/users/activity.ts
index 318cce77a5b93055f24e0247d21315f6355fdf55..d36e07a4415def5580e4beb6b04ae892b47a0e2f 100644
--- a/src/server/api/endpoints/aggregation/users/activity.ts
+++ b/src/server/api/endpoints/aggregation/users/activity.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import User from '../../../../../models/user';
 import Note from '../../../../../models/note';
 
@@ -9,9 +9,6 @@ import Note from '../../../../../models/note';
 
 /**
  * Aggregate activity of a user
- *
- * @param {any} params
- * @return {Promise<any>}
  */
 module.exports = (params) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
@@ -19,7 +16,7 @@ module.exports = (params) => new Promise(async (res, rej) => {
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'userId' parameter
-	const [userId, userIdErr] = $(params.userId).id().$;
+	const [userId, userIdErr] = $(params.userId).type(ID).$;
 	if (userIdErr) return rej('invalid userId param');
 
 	// Lookup user
diff --git a/src/server/api/endpoints/aggregation/users/followers.ts b/src/server/api/endpoints/aggregation/users/followers.ts
index 7ccb2a30661bdb6ee00a6705110890e3b69ef659..a6dd29e735f9c6d196b7cad93de34ef65edf5b50 100644
--- a/src/server/api/endpoints/aggregation/users/followers.ts
+++ b/src/server/api/endpoints/aggregation/users/followers.ts
@@ -1,19 +1,16 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import User from '../../../../../models/user';
 import FollowedLog from '../../../../../models/followed-log';
 
 /**
  * Aggregate followers of a user
- *
- * @param {any} params
- * @return {Promise<any>}
  */
 module.exports = (params) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
-	const [userId, userIdErr] = $(params.userId).id().$;
+	const [userId, userIdErr] = $(params.userId).type(ID).$;
 	if (userIdErr) return rej('invalid userId param');
 
 	// Lookup user
diff --git a/src/server/api/endpoints/aggregation/users/following.ts b/src/server/api/endpoints/aggregation/users/following.ts
index 45e246495b91856a3d0e85e3a470897ba1851785..7336f392fe7d577d913b2ef580178726d9955008 100644
--- a/src/server/api/endpoints/aggregation/users/following.ts
+++ b/src/server/api/endpoints/aggregation/users/following.ts
@@ -1,19 +1,16 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import User from '../../../../../models/user';
 import FollowingLog from '../../../../../models/following-log';
 
 /**
  * Aggregate following of a user
- *
- * @param {any} params
- * @return {Promise<any>}
  */
 module.exports = (params) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
-	const [userId, userIdErr] = $(params.userId).id().$;
+	const [userId, userIdErr] = $(params.userId).type(ID).$;
 	if (userIdErr) return rej('invalid userId param');
 
 	// Lookup user
diff --git a/src/server/api/endpoints/aggregation/users/post.ts b/src/server/api/endpoints/aggregation/users/post.ts
index e6170d83e233eca735aeb08b54189ca3d4d718d1..c5a5e5ffcaf04170aad443a83b3610ff6a30a472 100644
--- a/src/server/api/endpoints/aggregation/users/post.ts
+++ b/src/server/api/endpoints/aggregation/users/post.ts
@@ -1,19 +1,16 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import User from '../../../../../models/user';
 import Note from '../../../../../models/note';
 
 /**
  * Aggregate note of a user
- *
- * @param {any} params
- * @return {Promise<any>}
  */
 module.exports = (params) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
-	const [userId, userIdErr] = $(params.userId).id().$;
+	const [userId, userIdErr] = $(params.userId).type(ID).$;
 	if (userIdErr) return rej('invalid userId param');
 
 	// Lookup user
diff --git a/src/server/api/endpoints/aggregation/users/reaction.ts b/src/server/api/endpoints/aggregation/users/reaction.ts
index 881c7ea6931b1c76fd1b2ff9863b9196a288576c..f1664823cd9196d3249e8d405bfd0df5920eb4c0 100644
--- a/src/server/api/endpoints/aggregation/users/reaction.ts
+++ b/src/server/api/endpoints/aggregation/users/reaction.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import User from '../../../../../models/user';
 import Reaction from '../../../../../models/note-reaction';
 
@@ -13,7 +13,7 @@ import Reaction from '../../../../../models/note-reaction';
  */
 module.exports = (params) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
-	const [userId, userIdErr] = $(params.userId).id().$;
+	const [userId, userIdErr] = $(params.userId).type(ID).$;
 	if (userIdErr) return rej('invalid userId param');
 
 	// Lookup user
diff --git a/src/server/api/endpoints/app/create.ts b/src/server/api/endpoints/app/create.ts
index 4a55d33f2d547399593f53e10db4106ad6b394a0..f403429261006405ea1ae6df9640e120d10d361b 100644
--- a/src/server/api/endpoints/app/create.ts
+++ b/src/server/api/endpoints/app/create.ts
@@ -79,7 +79,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 	if (descriptionErr) return rej('invalid description param');
 
 	// Get 'permission' parameter
-	const [permission, permissionErr] = $(params.permission).array('string').unique().$;
+	const [permission, permissionErr] = $(params.permission).array($().string()).unique().$;
 	if (permissionErr) return rej('invalid permission param');
 
 	// Get 'callbackUrl' parameter
diff --git a/src/server/api/endpoints/app/show.ts b/src/server/api/endpoints/app/show.ts
index 99a2093b6839a6dfdcf695b5a43f8eaa6baea3ec..92a03b9838edb9cef145a415dc409a4192e88dbc 100644
--- a/src/server/api/endpoints/app/show.ts
+++ b/src/server/api/endpoints/app/show.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import App, { pack } from '../../../../models/app';
 
 /**
@@ -41,7 +41,7 @@ module.exports = (params, user, app) => new Promise(async (res, rej) => {
 	const isSecure = user != null && app == null;
 
 	// Get 'appId' parameter
-	const [appId, appIdErr] = $(params.appId).optional.id().$;
+	const [appId, appIdErr] = $(params.appId).optional.type(ID).$;
 	if (appIdErr) return rej('invalid appId param');
 
 	// Get 'nameId' parameter
diff --git a/src/server/api/endpoints/auth/accept.ts b/src/server/api/endpoints/auth/accept.ts
index b6297d663df2ec816386daba88cf32598980a993..e0073b31e61b46e5ddfc19b9f7e83261face08a7 100644
--- a/src/server/api/endpoints/auth/accept.ts
+++ b/src/server/api/endpoints/auth/accept.ts
@@ -3,7 +3,7 @@
  */
 import rndstr from 'rndstr';
 const crypto = require('crypto');
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import App from '../../../../models/app';
 import AuthSess from '../../../../models/auth-session';
 import AccessToken from '../../../../models/access-token';
diff --git a/src/server/api/endpoints/channels.ts b/src/server/api/endpoints/channels.ts
index 582e6ba43b55737083ad42364eab2163a9af88f9..b68107ed7d93dc942cc7cebfb022633b0512f521 100644
--- a/src/server/api/endpoints/channels.ts
+++ b/src/server/api/endpoints/channels.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../cafy-id';
 import Channel, { pack } from '../../../models/channel';
 
 /**
@@ -17,11 +17,11 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.type(ID).$;
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	const [untilId, untilIdErr] = $(params.untilId).optional.type(ID).$;
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Check if both of sinceId and untilId is specified
diff --git a/src/server/api/endpoints/channels/create.ts b/src/server/api/endpoints/channels/create.ts
index 0f0f558c8a4cee4edf092b6d14a66dcf643fd280..a737fcb152d190708e4bcaec4d4585adc519b3f3 100644
--- a/src/server/api/endpoints/channels/create.ts
+++ b/src/server/api/endpoints/channels/create.ts
@@ -8,10 +8,6 @@ import { pack } from '../../../../models/channel';
 
 /**
  * Create a channel
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = async (params, user) => new Promise(async (res, rej) => {
 	// Get 'title' parameter
diff --git a/src/server/api/endpoints/channels/notes.ts b/src/server/api/endpoints/channels/notes.ts
index d636aa0d10c366a932ba64eb098b69e602bf6723..73a69c6d2a212cf7bf7c98ae9991a896010ae1f4 100644
--- a/src/server/api/endpoints/channels/notes.ts
+++ b/src/server/api/endpoints/channels/notes.ts
@@ -1,16 +1,12 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import { default as Channel, IChannel } from '../../../../models/channel';
 import Note, { pack } from '../../../../models/note';
 
 /**
  * Show a notes of a channel
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
@@ -18,11 +14,11 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.type(ID).$;
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	const [untilId, untilIdErr] = $(params.untilId).optional.type(ID).$;
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Check if both of sinceId and untilId is specified
@@ -31,7 +27,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	}
 
 	// Get 'channelId' parameter
-	const [channelId, channelIdErr] = $(params.channelId).id().$;
+	const [channelId, channelIdErr] = $(params.channelId).type(ID).$;
 	if (channelIdErr) return rej('invalid channelId param');
 
 	// Fetch channel
diff --git a/src/server/api/endpoints/channels/show.ts b/src/server/api/endpoints/channels/show.ts
index 3ce9ce474550caf0bf9981abdd0dae39bc57a13c..3f468937eddb0f39720b692664a08122c20605fe 100644
--- a/src/server/api/endpoints/channels/show.ts
+++ b/src/server/api/endpoints/channels/show.ts
@@ -1,19 +1,15 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Channel, { IChannel, pack } from '../../../../models/channel';
 
 /**
  * Show a channel
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'channelId' parameter
-	const [channelId, channelIdErr] = $(params.channelId).id().$;
+	const [channelId, channelIdErr] = $(params.channelId).type(ID).$;
 	if (channelIdErr) return rej('invalid channelId param');
 
 	// Fetch channel
diff --git a/src/server/api/endpoints/channels/unwatch.ts b/src/server/api/endpoints/channels/unwatch.ts
index 8220b90b68a272112ff8c59fb8fc35fa2c3d051a..6ada3c9e1b27bc95af09ab53b851cec682779deb 100644
--- a/src/server/api/endpoints/channels/unwatch.ts
+++ b/src/server/api/endpoints/channels/unwatch.ts
@@ -1,20 +1,16 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Channel from '../../../../models/channel';
 import Watching from '../../../../models/channel-watching';
 
 /**
  * Unwatch a channel
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'channelId' parameter
-	const [channelId, channelIdErr] = $(params.channelId).id().$;
+	const [channelId, channelIdErr] = $(params.channelId).type(ID).$;
 	if (channelIdErr) return rej('invalid channelId param');
 
 	//#region Fetch channel
diff --git a/src/server/api/endpoints/channels/watch.ts b/src/server/api/endpoints/channels/watch.ts
index 6906282a546a6841bb497c01ad564dfaa8d8ad87..7880c3465255bbaf1a8a518ebf5f2331d713cb14 100644
--- a/src/server/api/endpoints/channels/watch.ts
+++ b/src/server/api/endpoints/channels/watch.ts
@@ -1,20 +1,16 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Channel from '../../../../models/channel';
 import Watching from '../../../../models/channel-watching';
 
 /**
  * Watch a channel
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'channelId' parameter
-	const [channelId, channelIdErr] = $(params.channelId).id().$;
+	const [channelId, channelIdErr] = $(params.channelId).type(ID).$;
 	if (channelIdErr) return rej('invalid channelId param');
 
 	//#region Fetch channel
diff --git a/src/server/api/endpoints/drive/files.ts b/src/server/api/endpoints/drive/files.ts
index 63d69d145a35766643961f34f33c58118c0cb11c..7f78ef9daa9507808caddef7feb1a9cab466cb76 100644
--- a/src/server/api/endpoints/drive/files.ts
+++ b/src/server/api/endpoints/drive/files.ts
@@ -1,16 +1,11 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import DriveFile, { pack } from '../../../../models/drive-file';
 
 /**
  * Get drive files
- *
- * @param {any} params
- * @param {any} user
- * @param {any} app
- * @return {Promise<any>}
  */
 module.exports = async (params, user, app) => {
 	// Get 'limit' parameter
@@ -18,11 +13,11 @@ module.exports = async (params, user, app) => {
 	if (limitErr) throw 'invalid limit param';
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.type(ID).$;
 	if (sinceIdErr) throw 'invalid sinceId param';
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	const [untilId, untilIdErr] = $(params.untilId).optional.type(ID).$;
 	if (untilIdErr) throw 'invalid untilId param';
 
 	// Check if both of sinceId and untilId is specified
@@ -31,7 +26,7 @@ module.exports = async (params, user, app) => {
 	}
 
 	// Get 'folderId' parameter
-	const [folderId = null, folderIdErr] = $(params.folderId).optional.nullable.id().$;
+	const [folderId = null, folderIdErr] = $(params.folderId).optional.nullable.type(ID).$;
 	if (folderIdErr) throw 'invalid folderId param';
 
 	// Get 'type' parameter
diff --git a/src/server/api/endpoints/drive/files/create.ts b/src/server/api/endpoints/drive/files/create.ts
index df0bd0a0d3c2ff9172a7b412450c16ce65599238..3d5048732d11622fcfa1366beeca02f611fe539e 100644
--- a/src/server/api/endpoints/drive/files/create.ts
+++ b/src/server/api/endpoints/drive/files/create.ts
@@ -1,17 +1,12 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import { validateFileName, pack } from '../../../../../models/drive-file';
 import create from '../../../../../services/drive/add-file';
 
 /**
  * Create a file
- *
- * @param {any} file
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = async (file, params, user): Promise<any> => {
 	if (file == null) {
@@ -34,7 +29,7 @@ module.exports = async (file, params, user): Promise<any> => {
 	}
 
 	// Get 'folderId' parameter
-	const [folderId = null, folderIdErr] = $(params.folderId).optional.nullable.id().$;
+	const [folderId = null, folderIdErr] = $(params.folderId).optional.nullable.type(ID).$;
 	if (folderIdErr) throw 'invalid folderId param';
 
 	try {
diff --git a/src/server/api/endpoints/drive/files/find.ts b/src/server/api/endpoints/drive/files/find.ts
index 0ab6e5d3e325ffd52d9180b7c268ff161341935e..5d49577983e1361c221ff6cb5e35b18c01641807 100644
--- a/src/server/api/endpoints/drive/files/find.ts
+++ b/src/server/api/endpoints/drive/files/find.ts
@@ -1,15 +1,11 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import DriveFile, { pack } from '../../../../../models/drive-file';
 
 /**
  * Find a file(s)
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'name' parameter
@@ -17,7 +13,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	if (nameErr) return rej('invalid name param');
 
 	// Get 'folderId' parameter
-	const [folderId = null, folderIdErr] = $(params.folderId).optional.nullable.id().$;
+	const [folderId = null, folderIdErr] = $(params.folderId).optional.nullable.type(ID).$;
 	if (folderIdErr) return rej('invalid folderId param');
 
 	// Issue query
diff --git a/src/server/api/endpoints/drive/files/show.ts b/src/server/api/endpoints/drive/files/show.ts
index 3398f24541cd7b5772fd3fb1a99b650e6da4c77f..93c3a63031696c13e914e0725d2cbdbe3d52c5bc 100644
--- a/src/server/api/endpoints/drive/files/show.ts
+++ b/src/server/api/endpoints/drive/files/show.ts
@@ -1,19 +1,15 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import DriveFile, { pack } from '../../../../../models/drive-file';
 
 /**
  * Show a file
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = async (params, user) => {
 	// Get 'fileId' parameter
-	const [fileId, fileIdErr] = $(params.fileId).id().$;
+	const [fileId, fileIdErr] = $(params.fileId).type(ID).$;
 	if (fileIdErr) throw 'invalid fileId param';
 
 	// Fetch file
diff --git a/src/server/api/endpoints/drive/files/update.ts b/src/server/api/endpoints/drive/files/update.ts
index c783ad8b3b78c45f6f65826db3b6f1e3e4d16670..3ac157b5301b2092c60be0f4568896318b366de6 100644
--- a/src/server/api/endpoints/drive/files/update.ts
+++ b/src/server/api/endpoints/drive/files/update.ts
@@ -1,21 +1,17 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import DriveFolder from '../../../../../models/drive-folder';
 import DriveFile, { validateFileName, pack } from '../../../../../models/drive-file';
 import { publishDriveStream } from '../../../../../publishers/stream';
 
 /**
  * Update a file
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'fileId' parameter
-	const [fileId, fileIdErr] = $(params.fileId).id().$;
+	const [fileId, fileIdErr] = $(params.fileId).type(ID).$;
 	if (fileIdErr) return rej('invalid fileId param');
 
 	// Fetch file
@@ -35,7 +31,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	if (name) file.filename = name;
 
 	// Get 'folderId' parameter
-	const [folderId, folderIdErr] = $(params.folderId).optional.nullable.id().$;
+	const [folderId, folderIdErr] = $(params.folderId).optional.nullable.type(ID).$;
 	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 8a426c0efccad06bfdeaff6f19562eeddb6e23d0..cfae1ae19217ceebf6aee126bf124788e22e8494 100644
--- a/src/server/api/endpoints/drive/files/upload_from_url.ts
+++ b/src/server/api/endpoints/drive/files/upload_from_url.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import { pack } from '../../../../../models/drive-file';
 import uploadFromUrl from '../../../../../services/drive/upload-from-url';
 
@@ -15,7 +15,7 @@ module.exports = async (params, user): Promise<any> => {
 	if (urlErr) throw 'invalid url param';
 
 	// Get 'folderId' parameter
-	const [folderId = null, folderIdErr] = $(params.folderId).optional.nullable.id().$;
+	const [folderId = null, folderIdErr] = $(params.folderId).optional.nullable.type(ID).$;
 	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 489e47912ebf1b5cbb0c589c4e1cea6083adc7cf..cba33c42866cd6b6869bcc884f0f82913c2e3cf6 100644
--- a/src/server/api/endpoints/drive/folders.ts
+++ b/src/server/api/endpoints/drive/folders.ts
@@ -1,16 +1,11 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import DriveFolder, { pack } from '../../../../models/drive-folder';
 
 /**
  * Get drive folders
- *
- * @param {any} params
- * @param {any} user
- * @param {any} app
- * @return {Promise<any>}
  */
 module.exports = (params, user, app) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
@@ -18,11 +13,11 @@ module.exports = (params, user, app) => new Promise(async (res, rej) => {
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.type(ID).$;
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	const [untilId, untilIdErr] = $(params.untilId).optional.type(ID).$;
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Check if both of sinceId and untilId is specified
@@ -31,7 +26,7 @@ module.exports = (params, user, app) => new Promise(async (res, rej) => {
 	}
 
 	// Get 'folderId' parameter
-	const [folderId = null, folderIdErr] = $(params.folderId).optional.nullable.id().$;
+	const [folderId = null, folderIdErr] = $(params.folderId).optional.nullable.type(ID).$;
 	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 f34d0019d74bcb86d88ac3a5d7fa898fbf576a65..65425537a2aee07c4631f6f89a9cc995efbafa3d 100644
--- a/src/server/api/endpoints/drive/folders/create.ts
+++ b/src/server/api/endpoints/drive/folders/create.ts
@@ -1,16 +1,12 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import DriveFolder, { isValidFolderName, pack } from '../../../../../models/drive-folder';
 import { publishDriveStream } from '../../../../../publishers/stream';
 
 /**
  * Create drive folder
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'name' parameter
@@ -18,7 +14,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	if (nameErr) return rej('invalid name param');
 
 	// Get 'parentId' parameter
-	const [parentId = null, parentIdErr] = $(params.parentId).optional.nullable.id().$;
+	const [parentId = null, parentIdErr] = $(params.parentId).optional.nullable.type(ID).$;
 	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 04dc38f87ff1078a426aecca3ae783b33a59586b..d6277f1978a5040e7a35b0642786d6393630aef7 100644
--- a/src/server/api/endpoints/drive/folders/find.ts
+++ b/src/server/api/endpoints/drive/folders/find.ts
@@ -1,15 +1,11 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import DriveFolder, { pack } from '../../../../../models/drive-folder';
 
 /**
  * Find a folder(s)
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'name' parameter
@@ -17,7 +13,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	if (nameErr) return rej('invalid name param');
 
 	// Get 'parentId' parameter
-	const [parentId = null, parentIdErr] = $(params.parentId).optional.nullable.id().$;
+	const [parentId = null, parentIdErr] = $(params.parentId).optional.nullable.type(ID).$;
 	if (parentIdErr) return rej('invalid parentId param');
 
 	// Issue query
diff --git a/src/server/api/endpoints/drive/folders/show.ts b/src/server/api/endpoints/drive/folders/show.ts
index b432f5a50af4212d3f7f08f962d7f48153912d02..c703209fefa4d23c77594c6848999ab730be1bb7 100644
--- a/src/server/api/endpoints/drive/folders/show.ts
+++ b/src/server/api/endpoints/drive/folders/show.ts
@@ -1,19 +1,15 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import DriveFolder, { pack } from '../../../../../models/drive-folder';
 
 /**
  * Show a folder
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'folderId' parameter
-	const [folderId, folderIdErr] = $(params.folderId).id().$;
+	const [folderId, folderIdErr] = $(params.folderId).type(ID).$;
 	if (folderIdErr) return rej('invalid folderId param');
 
 	// Get folder
diff --git a/src/server/api/endpoints/drive/folders/update.ts b/src/server/api/endpoints/drive/folders/update.ts
index dd7e8f5c8610e7d0c4c87a7d12de7fb0201554e0..d8da67fac82a3e6caed86187d2640ee083b7a6ec 100644
--- a/src/server/api/endpoints/drive/folders/update.ts
+++ b/src/server/api/endpoints/drive/folders/update.ts
@@ -1,20 +1,16 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import DriveFolder, { isValidFolderName, pack } from '../../../../../models/drive-folder';
 import { publishDriveStream } from '../../../../../publishers/stream';
 
 /**
  * Update a folder
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'folderId' parameter
-	const [folderId, folderIdErr] = $(params.folderId).id().$;
+	const [folderId, folderIdErr] = $(params.folderId).type(ID).$;
 	if (folderIdErr) return rej('invalid folderId param');
 
 	// Fetch folder
@@ -34,7 +30,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	if (name) folder.name = name;
 
 	// Get 'parentId' parameter
-	const [parentId, parentIdErr] = $(params.parentId).optional.nullable.id().$;
+	const [parentId, parentIdErr] = $(params.parentId).optional.nullable.type(ID).$;
 	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 02313aa37beccacb0c035b2c1d97500fa6d6ff87..00d89582b6a90f08a10427a16933fb312994ed5a 100644
--- a/src/server/api/endpoints/drive/stream.ts
+++ b/src/server/api/endpoints/drive/stream.ts
@@ -1,15 +1,11 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import DriveFile, { pack } from '../../../../models/drive-file';
 
 /**
  * Get drive stream
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
@@ -17,11 +13,11 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.type(ID).$;
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	const [untilId, untilIdErr] = $(params.untilId).optional.type(ID).$;
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Check if both of sinceId and untilId is specified
diff --git a/src/server/api/endpoints/following/create.ts b/src/server/api/endpoints/following/create.ts
index 27e5eb31dbd763de346ce686c564fb7e7d71077a..43f902852e4421debc3184328eda3703c64bf19a 100644
--- a/src/server/api/endpoints/following/create.ts
+++ b/src/server/api/endpoints/following/create.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import User from '../../../../models/user';
 import Following from '../../../../models/following';
 import create from '../../../../services/following/create';
@@ -13,7 +13,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	const follower = user;
 
 	// Get 'userId' parameter
-	const [userId, userIdErr] = $(params.userId).id().$;
+	const [userId, userIdErr] = $(params.userId).type(ID).$;
 	if (userIdErr) return rej('invalid userId param');
 
 	// 自分自身
diff --git a/src/server/api/endpoints/following/delete.ts b/src/server/api/endpoints/following/delete.ts
index ca0703ca224bf6c3a2247a33451dd18c56ccbaf3..99722ccf9186f4950dde94f52be2d992221a18a4 100644
--- a/src/server/api/endpoints/following/delete.ts
+++ b/src/server/api/endpoints/following/delete.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import User from '../../../../models/user';
 import Following from '../../../../models/following';
 import deleteFollowing from '../../../../services/following/delete';
@@ -13,7 +13,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	const follower = user;
 
 	// Get 'userId' parameter
-	const [userId, userIdErr] = $(params.userId).id().$;
+	const [userId, userIdErr] = $(params.userId).type(ID).$;
 	if (userIdErr) return rej('invalid userId param');
 
 	// Check if the followee is yourself
diff --git a/src/server/api/endpoints/following/stalk.ts b/src/server/api/endpoints/following/stalk.ts
index fc8be4924dce5d2ca83709198d7b8573680dd412..1dfbc4df986c0f53c900ec002d84b3a74fc8c055 100644
--- a/src/server/api/endpoints/following/stalk.ts
+++ b/src/server/api/endpoints/following/stalk.ts
@@ -1,6 +1,5 @@
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Following from '../../../../models/following';
-import { isLocalUser } from '../../../../models/user';
 
 /**
  * Stalk a user
@@ -9,7 +8,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	const follower = user;
 
 	// Get 'userId' parameter
-	const [userId, userIdErr] = $(params.userId).id().$;
+	const [userId, userIdErr] = $(params.userId).type(ID).$;
 	if (userIdErr) return rej('invalid userId param');
 
 	// Fetch following
diff --git a/src/server/api/endpoints/following/unstalk.ts b/src/server/api/endpoints/following/unstalk.ts
index d7593bcd003b42c4916981522ecf300ed95affc7..0d91ffeac80fb4bb0c2c7d7721ce1922378f8e8a 100644
--- a/src/server/api/endpoints/following/unstalk.ts
+++ b/src/server/api/endpoints/following/unstalk.ts
@@ -1,4 +1,4 @@
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Following from '../../../../models/following';
 
 /**
@@ -8,7 +8,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	const follower = user;
 
 	// Get 'userId' parameter
-	const [userId, userIdErr] = $(params.userId).id().$;
+	const [userId, userIdErr] = $(params.userId).type(ID).$;
 	if (userIdErr) return rej('invalid userId param');
 
 	// Fetch following
diff --git a/src/server/api/endpoints/i/authorized_apps.ts b/src/server/api/endpoints/i/authorized_apps.ts
index 82fd2d251698d5d3af4c03cd890ecc73b40eb8a4..fd12b3dec02d0f1fbc59aaeece2ffcf908183819 100644
--- a/src/server/api/endpoints/i/authorized_apps.ts
+++ b/src/server/api/endpoints/i/authorized_apps.ts
@@ -7,10 +7,6 @@ import { pack } from '../../../../models/app';
 
 /**
  * Get authorized apps of my account
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
diff --git a/src/server/api/endpoints/i/change_password.ts b/src/server/api/endpoints/i/change_password.ts
index 57415083f18227facf3276aac3065f8f102c1bd2..a24e9f0be11ffeb6620e6b2ec4ffa844f52790bd 100644
--- a/src/server/api/endpoints/i/change_password.ts
+++ b/src/server/api/endpoints/i/change_password.ts
@@ -7,10 +7,6 @@ import User from '../../../../models/user';
 
 /**
  * Change password
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = async (params, user) => new Promise(async (res, rej) => {
 	// Get 'currentPasword' parameter
diff --git a/src/server/api/endpoints/i/favorites.ts b/src/server/api/endpoints/i/favorites.ts
index f390ef9ec76a91fc1e0fbae3ce988e9409483a50..a2c472ad179ccf38f2aa03d4db52ecd3a4be283c 100644
--- a/src/server/api/endpoints/i/favorites.ts
+++ b/src/server/api/endpoints/i/favorites.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Favorite, { pack } from '../../../../models/favorite';
 
 /**
@@ -13,11 +13,11 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.type(ID).$;
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	const [untilId, untilIdErr] = $(params.untilId).optional.type(ID).$;
 	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 69a8910898555d7a362abbac58a2606b582ed3ba..14ade7b023652680cab859f811ddba2de2d203eb 100644
--- a/src/server/api/endpoints/i/notifications.ts
+++ b/src/server/api/endpoints/i/notifications.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Notification from '../../../../models/notification';
 import Mute from '../../../../models/mute';
 import { pack } from '../../../../models/notification';
@@ -22,7 +22,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	if (markAsReadErr) return rej('invalid markAsRead param');
 
 	// Get 'type' parameter
-	const [type, typeErr] = $(params.type).optional.array('string').unique().$;
+	const [type, typeErr] = $(params.type).optional.array($().string()).unique().$;
 	if (typeErr) return rej('invalid type param');
 
 	// Get 'limit' parameter
@@ -30,11 +30,11 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.type(ID).$;
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	const [untilId, untilIdErr] = $(params.untilId).optional.type(ID).$;
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Check if both of sinceId and untilId is specified
diff --git a/src/server/api/endpoints/i/pin.ts b/src/server/api/endpoints/i/pin.ts
index 909a6fdbdef9e77422d273adf8c24fe6adb32fde..761e41bbeaa636bc67a82bf2e21e1ccabc16c856 100644
--- a/src/server/api/endpoints/i/pin.ts
+++ b/src/server/api/endpoints/i/pin.ts
@@ -1,21 +1,17 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import User from '../../../../models/user';
 import Note from '../../../../models/note';
 import { pack } from '../../../../models/user';
 
 /**
  * Pin note
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = async (params, user) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
-	const [noteId, noteIdErr] = $(params.noteId).id().$;
+	const [noteId, noteIdErr] = $(params.noteId).type(ID).$;
 	if (noteIdErr) return rej('invalid noteId param');
 
 	// Fetch pinee
diff --git a/src/server/api/endpoints/i/regenerate_token.ts b/src/server/api/endpoints/i/regenerate_token.ts
index f9e92c1797fcc86f6a5c0947a505b8629c4ae2bf..945ddbdee46079a356a55e2725ffb34903b68106 100644
--- a/src/server/api/endpoints/i/regenerate_token.ts
+++ b/src/server/api/endpoints/i/regenerate_token.ts
@@ -9,10 +9,6 @@ import generateUserToken from '../../common/generate-native-user-token';
 
 /**
  * Regenerate native token
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = async (params, user) => new Promise(async (res, rej) => {
 	// Get 'password' parameter
diff --git a/src/server/api/endpoints/i/signin_history.ts b/src/server/api/endpoints/i/signin_history.ts
index 931b9e2252e636d5038ebb802c8dcaaae1fc9924..77beca9fd6d97b55ff10a4251cd4a510379da0c5 100644
--- a/src/server/api/endpoints/i/signin_history.ts
+++ b/src/server/api/endpoints/i/signin_history.ts
@@ -1,15 +1,11 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Signin, { pack } from '../../../../models/signin';
 
 /**
  * Get signin history of my account
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
@@ -17,11 +13,11 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.type(ID).$;
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	const [untilId, untilIdErr] = $(params.untilId).optional.type(ID).$;
 	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 f3c9d777b5b546de851978af77bbb55ab95c0e26..7505e7338709dc0bf0533657902fc4d821e5ac33 100644
--- a/src/server/api/endpoints/i/update.ts
+++ b/src/server/api/endpoints/i/update.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import User, { isValidName, isValidDescription, isValidLocation, isValidBirthday, pack } from '../../../../models/user';
 import event from '../../../../publishers/stream';
 
@@ -32,12 +32,12 @@ module.exports = async (params, user, app) => new Promise(async (res, rej) => {
 	if (birthday !== undefined) user.profile.birthday = birthday;
 
 	// Get 'avatarId' parameter
-	const [avatarId, avatarIdErr] = $(params.avatarId).optional.id().$;
+	const [avatarId, avatarIdErr] = $(params.avatarId).optional.type(ID).$;
 	if (avatarIdErr) return rej('invalid avatarId param');
 	if (avatarId) user.avatarId = avatarId;
 
 	// Get 'bannerId' parameter
-	const [bannerId, bannerIdErr] = $(params.bannerId).optional.id().$;
+	const [bannerId, bannerIdErr] = $(params.bannerId).optional.type(ID).$;
 	if (bannerIdErr) return rej('invalid bannerId param');
 	if (bannerId) user.bannerId = bannerId;
 
diff --git a/src/server/api/endpoints/i/update_client_setting.ts b/src/server/api/endpoints/i/update_client_setting.ts
index b0d5db5ec2337343167c71bfe6e4afb903d29de5..f753c8bcc412a71c12fcf7e101f48ee7f5302b8e 100644
--- a/src/server/api/endpoints/i/update_client_setting.ts
+++ b/src/server/api/endpoints/i/update_client_setting.ts
@@ -7,10 +7,6 @@ import event from '../../../../publishers/stream';
 
 /**
  * Update myself
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = async (params, user) => new Promise(async (res, rej) => {
 	// Get 'name' parameter
diff --git a/src/server/api/endpoints/i/update_home.ts b/src/server/api/endpoints/i/update_home.ts
index ce7661ede0822de263755451cf776291345452fd..4b8ba25069bff478cb17961215693cf7fc1ca2e7 100644
--- a/src/server/api/endpoints/i/update_home.ts
+++ b/src/server/api/endpoints/i/update_home.ts
@@ -8,7 +8,7 @@ import event from '../../../../publishers/stream';
 module.exports = async (params, user) => new Promise(async (res, rej) => {
 	// Get 'home' parameter
 	const [home, homeErr] = $(params.home).optional.array().each(
-		$().strict.object()
+		$().object(true)
 			.have('name', $().string())
 			.have('id', $().string())
 			.have('place', $().string())
diff --git a/src/server/api/endpoints/i/update_mobile_home.ts b/src/server/api/endpoints/i/update_mobile_home.ts
index b710e2f330e6db1c3c9126045b981796d0dae37a..c3ecea71780ac00f3943ddeed79f43331f8896a9 100644
--- a/src/server/api/endpoints/i/update_mobile_home.ts
+++ b/src/server/api/endpoints/i/update_mobile_home.ts
@@ -8,7 +8,7 @@ import event from '../../../../publishers/stream';
 module.exports = async (params, user) => new Promise(async (res, rej) => {
 	// Get 'home' parameter
 	const [home, homeErr] = $(params.home).optional.array().each(
-		$().strict.object()
+		$().object(true)
 			.have('name', $().string())
 			.have('id', $().string())
 			.have('data', $().object())).$;
diff --git a/src/server/api/endpoints/messaging/history.ts b/src/server/api/endpoints/messaging/history.ts
index e42d34f21a9f99eb315b53b01d2b86e3fb16ea14..654bf5c198e66bb7b73a2bb99589f9f6bd7f162a 100644
--- a/src/server/api/endpoints/messaging/history.ts
+++ b/src/server/api/endpoints/messaging/history.ts
@@ -8,10 +8,6 @@ import { pack } from '../../../../models/messaging-message';
 
 /**
  * Show messaging history
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
diff --git a/src/server/api/endpoints/messaging/messages.ts b/src/server/api/endpoints/messaging/messages.ts
index 092eab0562ce8f8a279b6f384d3de8db29e2b625..f28699cb88a54a62ffd921904f312e9b73293393 100644
--- a/src/server/api/endpoints/messaging/messages.ts
+++ b/src/server/api/endpoints/messaging/messages.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Message from '../../../../models/messaging-message';
 import User from '../../../../models/user';
 import { pack } from '../../../../models/messaging-message';
@@ -16,7 +16,7 @@ import read from '../../common/read-messaging-message';
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
-	const [recipientId, recipientIdErr] = $(params.userId).id().$;
+	const [recipientId, recipientIdErr] = $(params.userId).type(ID).$;
 	if (recipientIdErr) return rej('invalid userId param');
 
 	// Fetch recipient
@@ -41,11 +41,11 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.type(ID).$;
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	const [untilId, untilIdErr] = $(params.untilId).optional.type(ID).$;
 	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 0483b602b299c823e6da1f179de76ff5d2852329..cce326be6eb965ed19d2504bcd25487b4c3593d3 100644
--- a/src/server/api/endpoints/messaging/messages/create.ts
+++ b/src/server/api/endpoints/messaging/messages/create.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import Message from '../../../../../models/messaging-message';
 import { isValidText } from '../../../../../models/messaging-message';
 import History from '../../../../../models/messaging-history';
@@ -16,14 +16,10 @@ import config from '../../../../../config';
 
 /**
  * Create a message
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
-	const [recipientId, recipientIdErr] = $(params.userId).id().$;
+	const [recipientId, recipientIdErr] = $(params.userId).type(ID).$;
 	if (recipientIdErr) return rej('invalid userId param');
 
 	// Myself
@@ -49,7 +45,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	if (textErr) return rej('invalid text');
 
 	// Get 'fileId' parameter
-	const [fileId, fileIdErr] = $(params.fileId).optional.id().$;
+	const [fileId, fileIdErr] = $(params.fileId).optional.type(ID).$;
 	if (fileIdErr) return rej('invalid fileId param');
 
 	let file = null;
diff --git a/src/server/api/endpoints/messaging/unread.ts b/src/server/api/endpoints/messaging/unread.ts
index 30d59dd8bdb0c9b52d859011ef0df81c2cb6027f..1d83af501d392de1e9c681a3332c2e73a8cb288f 100644
--- a/src/server/api/endpoints/messaging/unread.ts
+++ b/src/server/api/endpoints/messaging/unread.ts
@@ -6,10 +6,6 @@ import Mute from '../../../../models/mute';
 
 /**
  * Get count of unread messages
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	const mute = await Mute.find({
diff --git a/src/server/api/endpoints/mute/create.ts b/src/server/api/endpoints/mute/create.ts
index 26ae612cab248d646a9dfb158fe15dafc3cd9f91..0d59ecc118bb49d43bee6f353893f1b79c818746 100644
--- a/src/server/api/endpoints/mute/create.ts
+++ b/src/server/api/endpoints/mute/create.ts
@@ -1,22 +1,18 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import User from '../../../../models/user';
 import Mute from '../../../../models/mute';
 
 /**
  * Mute a user
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	const muter = user;
 
 	// Get 'userId' parameter
-	const [userId, userIdErr] = $(params.userId).id().$;
+	const [userId, userIdErr] = $(params.userId).type(ID).$;
 	if (userIdErr) return rej('invalid userId param');
 
 	// 自分自身
diff --git a/src/server/api/endpoints/mute/delete.ts b/src/server/api/endpoints/mute/delete.ts
index 6f617416c8ed121693aec7ad3c308ded4f67074a..3a37de9a214f4074bb1a3b8d22c93be421ebe476 100644
--- a/src/server/api/endpoints/mute/delete.ts
+++ b/src/server/api/endpoints/mute/delete.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import User from '../../../../models/user';
 import Mute from '../../../../models/mute';
 
@@ -12,7 +12,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	const muter = user;
 
 	// Get 'userId' parameter
-	const [userId, userIdErr] = $(params.userId).id().$;
+	const [userId, userIdErr] = $(params.userId).type(ID).$;
 	if (userIdErr) return rej('invalid userId param');
 
 	// Check if the mutee is yourself
diff --git a/src/server/api/endpoints/mute/list.ts b/src/server/api/endpoints/mute/list.ts
index 0b8262d6c59e826619e87afcb067de2e6dc51bb0..f35bf7d168086b3fd64b931765d00e1e7397bf1e 100644
--- a/src/server/api/endpoints/mute/list.ts
+++ b/src/server/api/endpoints/mute/list.ts
@@ -1,17 +1,13 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Mute from '../../../../models/mute';
 import { pack } from '../../../../models/user';
 import { getFriendIds } from '../../common/get-friends';
 
 /**
  * Get muted users of a user
- *
- * @param {any} params
- * @param {any} me
- * @return {Promise<any>}
  */
 module.exports = (params, me) => new Promise(async (res, rej) => {
 	// Get 'iknow' parameter
@@ -23,7 +19,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'cursor' parameter
-	const [cursor = null, cursorErr] = $(params.cursor).optional.id().$;
+	const [cursor = null, cursorErr] = $(params.cursor).optional.type(ID).$;
 	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 2a3f8bcd7a9e9e560e1db97bfd42ef479667cd0f..eb7ece70e9a1160d0982422034a099c455806822 100644
--- a/src/server/api/endpoints/my/apps.ts
+++ b/src/server/api/endpoints/my/apps.ts
@@ -6,10 +6,6 @@ import App, { pack } from '../../../../models/app';
 
 /**
  * Get my apps
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
diff --git a/src/server/api/endpoints/notes.ts b/src/server/api/endpoints/notes.ts
index a70ac0588f6acbf4cb2359e819470634b659dd41..bf4d5bc66fa395f63afa2367eddbf4e915ec79a4 100644
--- a/src/server/api/endpoints/notes.ts
+++ b/src/server/api/endpoints/notes.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../cafy-id';
 import Note, { pack } from '../../../models/note';
 
 /**
@@ -33,11 +33,11 @@ module.exports = (params) => new Promise(async (res, rej) => {
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.type(ID).$;
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	const [untilId, untilIdErr] = $(params.untilId).optional.type(ID).$;
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Check if both of sinceId and untilId is specified
diff --git a/src/server/api/endpoints/notes/context.ts b/src/server/api/endpoints/notes/context.ts
index 2caf742d26600fe44f719e40f339cece8bbc5cd6..309fc2644760456dc80d505a2f654877444c9e1d 100644
--- a/src/server/api/endpoints/notes/context.ts
+++ b/src/server/api/endpoints/notes/context.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note, { pack } from '../../../../models/note';
 
 /**
@@ -13,7 +13,7 @@ import Note, { pack } from '../../../../models/note';
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
-	const [noteId, noteIdErr] = $(params.noteId).id().$;
+	const [noteId, noteIdErr] = $(params.noteId).type(ID).$;
 	if (noteIdErr) return rej('invalid noteId param');
 
 	// Get 'limit' parameter
diff --git a/src/server/api/endpoints/notes/create.ts b/src/server/api/endpoints/notes/create.ts
index ea1f41aae2713ecaec50a5352272f3de8967429a..1824a16c24d697895bd6f93bd12f4d67f3bf7bca 100644
--- a/src/server/api/endpoints/notes/create.ts
+++ b/src/server/api/endpoints/notes/create.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note, { INote, isValidText, isValidCw, pack } from '../../../../models/note';
 import { ILocalUser } from '../../../../models/user';
 import Channel, { IChannel } from '../../../../models/channel';
@@ -11,11 +11,6 @@ import { IApp } from '../../../../models/app';
 
 /**
  * Create a note
- *
- * @param {any} params
- * @param {any} user
- * @param {any} app
- * @return {Promise<any>}
  */
 module.exports = (params, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => {
 	// Get 'visibility' parameter
@@ -35,11 +30,11 @@ module.exports = (params, user: ILocalUser, app: IApp) => new Promise(async (res
 	if (viaMobileErr) return rej('invalid viaMobile');
 
 	// Get 'tags' parameter
-	const [tags = [], tagsErr] = $(params.tags).optional.array('string').unique().eachQ(t => t.range(1, 32)).$;
+	const [tags = [], tagsErr] = $(params.tags).optional.array($().string().range(1, 32)).unique().$;
 	if (tagsErr) return rej('invalid tags');
 
 	// Get 'geo' parameter
-	const [geo, geoErr] = $(params.geo).optional.nullable.strict.object()
+	const [geo, geoErr] = $(params.geo).optional.nullable.object(true)
 		.have('coordinates', $().array().length(2)
 			.item(0, $().number().range(-180, 180))
 			.item(1, $().number().range(-90, 90)))
@@ -52,7 +47,7 @@ module.exports = (params, user: ILocalUser, app: IApp) => new Promise(async (res
 	if (geoErr) return rej('invalid geo');
 
 	// Get 'mediaIds' parameter
-	const [mediaIds, mediaIdsErr] = $(params.mediaIds).optional.array('id').unique().range(1, 4).$;
+	const [mediaIds, mediaIdsErr] = $(params.mediaIds).optional.array($().type(ID)).unique().range(1, 4).$;
 	if (mediaIdsErr) return rej('invalid mediaIds');
 
 	let files = [];
@@ -79,7 +74,7 @@ module.exports = (params, user: ILocalUser, app: IApp) => new Promise(async (res
 	}
 
 	// Get 'renoteId' parameter
-	const [renoteId, renoteIdErr] = $(params.renoteId).optional.id().$;
+	const [renoteId, renoteIdErr] = $(params.renoteId).optional.type(ID).$;
 	if (renoteIdErr) return rej('invalid renoteId');
 
 	let renote: INote = null;
@@ -100,7 +95,7 @@ module.exports = (params, user: ILocalUser, app: IApp) => new Promise(async (res
 	}
 
 	// Get 'replyId' parameter
-	const [replyId, replyIdErr] = $(params.replyId).optional.id().$;
+	const [replyId, replyIdErr] = $(params.replyId).optional.type(ID).$;
 	if (replyIdErr) return rej('invalid replyId');
 
 	let reply: INote = null;
@@ -121,7 +116,7 @@ module.exports = (params, user: ILocalUser, app: IApp) => new Promise(async (res
 	}
 
 	// Get 'channelId' parameter
-	const [channelId, channelIdErr] = $(params.channelId).optional.id().$;
+	const [channelId, channelIdErr] = $(params.channelId).optional.type(ID).$;
 	if (channelIdErr) return rej('invalid channelId');
 
 	let channel: IChannel = null;
@@ -162,8 +157,8 @@ module.exports = (params, user: ILocalUser, app: IApp) => new Promise(async (res
 	}
 
 	// Get 'poll' parameter
-	const [poll, pollErr] = $(params.poll).optional.strict.object()
-		.have('choices', $().array('string')
+	const [poll, pollErr] = $(params.poll).optional.object(true)
+		.have('choices', $().array($().string())
 			.unique()
 			.range(2, 10)
 			.each(c => c.length > 0 && c.length < 50))
diff --git a/src/server/api/endpoints/notes/favorites/create.ts b/src/server/api/endpoints/notes/favorites/create.ts
index c8e7f524269c1888d02226eea41244578585c4de..e4c4adb9bbb8bc24b38bde49cb5e167927e031e5 100644
--- a/src/server/api/endpoints/notes/favorites/create.ts
+++ b/src/server/api/endpoints/notes/favorites/create.ts
@@ -1,20 +1,16 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import Favorite from '../../../../../models/favorite';
 import Note from '../../../../../models/note';
 
 /**
  * Favorite a note
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
-	const [noteId, noteIdErr] = $(params.noteId).id().$;
+	const [noteId, noteIdErr] = $(params.noteId).type(ID).$;
 	if (noteIdErr) return rej('invalid noteId param');
 
 	// Get favoritee
diff --git a/src/server/api/endpoints/notes/favorites/delete.ts b/src/server/api/endpoints/notes/favorites/delete.ts
index 92aceb343b9f0b6c9f6aadd1b4cb64412ccb7b07..3c4d9a11118c91ce98d6d71a1923ad5aa244318b 100644
--- a/src/server/api/endpoints/notes/favorites/delete.ts
+++ b/src/server/api/endpoints/notes/favorites/delete.ts
@@ -1,20 +1,16 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import Favorite from '../../../../../models/favorite';
 import Note from '../../../../../models/note';
 
 /**
  * Unfavorite a note
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
-	const [noteId, noteIdErr] = $(params.noteId).id().$;
+	const [noteId, noteIdErr] = $(params.noteId).type(ID).$;
 	if (noteIdErr) return rej('invalid noteId param');
 
 	// Get favoritee
diff --git a/src/server/api/endpoints/notes/global-timeline.ts b/src/server/api/endpoints/notes/global-timeline.ts
index 07e138ec54293bd1dae809aeb9fb3c1eff01a8c4..e2a94d8a3eb6421b3fef28b541a1437001a177a7 100644
--- a/src/server/api/endpoints/notes/global-timeline.ts
+++ b/src/server/api/endpoints/notes/global-timeline.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note from '../../../../models/note';
 import Mute from '../../../../models/mute';
 import { pack } from '../../../../models/note';
@@ -15,11 +15,11 @@ module.exports = async (params, user, app) => {
 	if (limitErr) throw 'invalid limit param';
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.type(ID).$;
 	if (sinceIdErr) throw 'invalid sinceId param';
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	const [untilId, untilIdErr] = $(params.untilId).optional.type(ID).$;
 	if (untilIdErr) throw 'invalid untilId param';
 
 	// Get 'sinceDate' parameter
diff --git a/src/server/api/endpoints/notes/local-timeline.ts b/src/server/api/endpoints/notes/local-timeline.ts
index d63528c3cdda46ac4ef9d54e978bd84ab50b4e85..dda83311ac23e9dd6d73bb40960f348bec476601 100644
--- a/src/server/api/endpoints/notes/local-timeline.ts
+++ b/src/server/api/endpoints/notes/local-timeline.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note from '../../../../models/note';
 import Mute from '../../../../models/mute';
 import { pack } from '../../../../models/note';
@@ -15,11 +15,11 @@ module.exports = async (params, user, app) => {
 	if (limitErr) throw 'invalid limit param';
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.type(ID).$;
 	if (sinceIdErr) throw 'invalid sinceId param';
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	const [untilId, untilIdErr] = $(params.untilId).optional.type(ID).$;
 	if (untilIdErr) throw 'invalid untilId param';
 
 	// Get 'sinceDate' parameter
diff --git a/src/server/api/endpoints/notes/mentions.ts b/src/server/api/endpoints/notes/mentions.ts
index 2d95606b3f3a310f84bab612dbe82079eab25b58..815cf271a215764ab374556fb210f4dc848e97e5 100644
--- a/src/server/api/endpoints/notes/mentions.ts
+++ b/src/server/api/endpoints/notes/mentions.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note from '../../../../models/note';
 import { getFriendIds } from '../../common/get-friends';
 import { pack } from '../../../../models/note';
@@ -24,11 +24,11 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.type(ID).$;
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	const [untilId, untilIdErr] = $(params.untilId).optional.type(ID).$;
 	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 cb530ea2cfb4dc873d0cbc0b249c6a2d1923acf2..24b0a4c803abc57b3fa16138f4c3354036f1cb0b 100644
--- a/src/server/api/endpoints/notes/polls/recommendation.ts
+++ b/src/server/api/endpoints/notes/polls/recommendation.ts
@@ -7,10 +7,6 @@ import Note, { pack } from '../../../../../models/note';
 
 /**
  * Get recommended polls
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
diff --git a/src/server/api/endpoints/notes/polls/vote.ts b/src/server/api/endpoints/notes/polls/vote.ts
index 03d94da60d3f8ee72c41fc719e12a6f66fdcdd4d..2669c39085ada605147ec8b4fe14e090e81c0852 100644
--- a/src/server/api/endpoints/notes/polls/vote.ts
+++ b/src/server/api/endpoints/notes/polls/vote.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import Vote from '../../../../../models/poll-vote';
 import Note from '../../../../../models/note';
 import Watching from '../../../../../models/note-watching';
@@ -11,14 +11,10 @@ import notify from '../../../../../publishers/notify';
 
 /**
  * Vote poll of a note
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
-	const [noteId, noteIdErr] = $(params.noteId).id().$;
+	const [noteId, noteIdErr] = $(params.noteId).type(ID).$;
 	if (noteIdErr) return rej('invalid noteId param');
 
 	// Get votee
diff --git a/src/server/api/endpoints/notes/reactions.ts b/src/server/api/endpoints/notes/reactions.ts
index bbff97bb0a5765f263d05e9254eae4e106bd4c9f..68ffbacd4675c9aa704f37cd12509a51dc97eed0 100644
--- a/src/server/api/endpoints/notes/reactions.ts
+++ b/src/server/api/endpoints/notes/reactions.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note from '../../../../models/note';
 import Reaction, { pack } from '../../../../models/note-reaction';
 
@@ -14,7 +14,7 @@ import Reaction, { pack } from '../../../../models/note-reaction';
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
-	const [noteId, noteIdErr] = $(params.noteId).id().$;
+	const [noteId, noteIdErr] = $(params.noteId).type(ID).$;
 	if (noteIdErr) return rej('invalid noteId param');
 
 	// Get 'limit' parameter
diff --git a/src/server/api/endpoints/notes/reactions/create.ts b/src/server/api/endpoints/notes/reactions/create.ts
index 9e217cc3e03062d7c741b016efc9e0c7f0fce9f6..1c212526046ff1df22dcd9688eeb2000628b50d2 100644
--- a/src/server/api/endpoints/notes/reactions/create.ts
+++ b/src/server/api/endpoints/notes/reactions/create.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import Note from '../../../../../models/note';
 import create from '../../../../../services/note/reaction/create';
 import { validateReaction } from '../../../../../models/note-reaction';
@@ -11,7 +11,7 @@ import { validateReaction } from '../../../../../models/note-reaction';
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
-	const [noteId, noteIdErr] = $(params.noteId).id().$;
+	const [noteId, noteIdErr] = $(params.noteId).type(ID).$;
 	if (noteIdErr) return rej('invalid noteId param');
 
 	// Get 'reaction' parameter
diff --git a/src/server/api/endpoints/notes/reactions/delete.ts b/src/server/api/endpoints/notes/reactions/delete.ts
index b5d738b8ffeff00386b80b511caa787de70ba0ec..be3c1b214dd52b7dbca135692dc74640b635ac64 100644
--- a/src/server/api/endpoints/notes/reactions/delete.ts
+++ b/src/server/api/endpoints/notes/reactions/delete.ts
@@ -1,21 +1,16 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import Reaction from '../../../../../models/note-reaction';
 import Note from '../../../../../models/note';
-// import event from '../../../publishers/stream';
 
 /**
  * Unreact to a note
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
-	const [noteId, noteIdErr] = $(params.noteId).id().$;
+	const [noteId, noteIdErr] = $(params.noteId).type(ID).$;
 	if (noteIdErr) return rej('invalid noteId param');
 
 	// Fetch unreactee
diff --git a/src/server/api/endpoints/notes/replies.ts b/src/server/api/endpoints/notes/replies.ts
index 88d9ff329a74b3f9efa07727d4eb081fa7498e4b..31f1bb941aea046a14c47670065129c201f977ea 100644
--- a/src/server/api/endpoints/notes/replies.ts
+++ b/src/server/api/endpoints/notes/replies.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note, { pack } from '../../../../models/note';
 
 /**
@@ -13,7 +13,7 @@ import Note, { pack } from '../../../../models/note';
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
-	const [noteId, noteIdErr] = $(params.noteId).id().$;
+	const [noteId, noteIdErr] = $(params.noteId).type(ID).$;
 	if (noteIdErr) return rej('invalid noteId param');
 
 	// Get 'limit' parameter
diff --git a/src/server/api/endpoints/notes/reposts.ts b/src/server/api/endpoints/notes/reposts.ts
index 9dfc2c3cb5c3dcbb934ca6a0eddb45857cd5e337..fe989313804312e98230b776cc6f3b0e7c0ab23f 100644
--- a/src/server/api/endpoints/notes/reposts.ts
+++ b/src/server/api/endpoints/notes/reposts.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note, { pack } from '../../../../models/note';
 
 /**
@@ -13,7 +13,7 @@ import Note, { pack } from '../../../../models/note';
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
-	const [noteId, noteIdErr] = $(params.noteId).id().$;
+	const [noteId, noteIdErr] = $(params.noteId).type(ID).$;
 	if (noteIdErr) return rej('invalid noteId param');
 
 	// Get 'limit' parameter
@@ -21,11 +21,11 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.type(ID).$;
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	const [untilId, untilIdErr] = $(params.untilId).optional.type(ID).$;
 	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 3ff3fbbafa8cdd5677a62dcbcc41ef97a603f9ea..021f620aa294b0dc0023e9dc0a3a5c169b5735d3 100644
--- a/src/server/api/endpoints/notes/search.ts
+++ b/src/server/api/endpoints/notes/search.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 const escapeRegexp = require('escape-regexp');
 import Note from '../../../../models/note';
 import User from '../../../../models/user';
@@ -22,19 +22,19 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 	if (textError) return rej('invalid text param');
 
 	// Get 'includeUserIds' parameter
-	const [includeUserIds = [], includeUserIdsErr] = $(params.includeUserIds).optional.array('id').$;
+	const [includeUserIds = [], includeUserIdsErr] = $(params.includeUserIds).optional.array($().type(ID)).$;
 	if (includeUserIdsErr) return rej('invalid includeUserIds param');
 
 	// Get 'excludeUserIds' parameter
-	const [excludeUserIds = [], excludeUserIdsErr] = $(params.excludeUserIds).optional.array('id').$;
+	const [excludeUserIds = [], excludeUserIdsErr] = $(params.excludeUserIds).optional.array($().type(ID)).$;
 	if (excludeUserIdsErr) return rej('invalid excludeUserIds param');
 
 	// Get 'includeUserUsernames' parameter
-	const [includeUserUsernames = [], includeUserUsernamesErr] = $(params.includeUserUsernames).optional.array('string').$;
+	const [includeUserUsernames = [], includeUserUsernamesErr] = $(params.includeUserUsernames).optional.array($().string()).$;
 	if (includeUserUsernamesErr) return rej('invalid includeUserUsernames param');
 
 	// Get 'excludeUserUsernames' parameter
-	const [excludeUserUsernames = [], excludeUserUsernamesErr] = $(params.excludeUserUsernames).optional.array('string').$;
+	const [excludeUserUsernames = [], excludeUserUsernamesErr] = $(params.excludeUserUsernames).optional.array($().string()).$;
 	if (excludeUserUsernamesErr) return rej('invalid excludeUserUsernames param');
 
 	// Get 'following' parameter
diff --git a/src/server/api/endpoints/notes/show.ts b/src/server/api/endpoints/notes/show.ts
index 67cdc3038bad5a06644fb2ad238530c44854ee94..266e0687e97d29ee4ba50f98cc33b9b87e2c91c5 100644
--- a/src/server/api/endpoints/notes/show.ts
+++ b/src/server/api/endpoints/notes/show.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note, { pack } from '../../../../models/note';
 
 /**
@@ -13,7 +13,7 @@ import Note, { pack } from '../../../../models/note';
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
-	const [noteId, noteIdErr] = $(params.noteId).id().$;
+	const [noteId, noteIdErr] = $(params.noteId).type(ID).$;
 	if (noteIdErr) return rej('invalid noteId param');
 
 	// Get note
diff --git a/src/server/api/endpoints/notes/timeline.ts b/src/server/api/endpoints/notes/timeline.ts
index de30afea57d8beadf04207b8f71addd2f8fccb19..476d64158c42e71d6fcd3b3b0fbbca90f119bcb0 100644
--- a/src/server/api/endpoints/notes/timeline.ts
+++ b/src/server/api/endpoints/notes/timeline.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note from '../../../../models/note';
 import Mute from '../../../../models/mute';
 import ChannelWatching from '../../../../models/channel-watching';
@@ -17,11 +17,11 @@ module.exports = async (params, user, app) => {
 	if (limitErr) throw 'invalid limit param';
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.type(ID).$;
 	if (sinceIdErr) throw 'invalid sinceId param';
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	const [untilId, untilIdErr] = $(params.untilId).optional.type(ID).$;
 	if (untilIdErr) throw 'invalid untilId param';
 
 	// Get 'sinceDate' parameter
diff --git a/src/server/api/endpoints/notes/trend.ts b/src/server/api/endpoints/notes/trend.ts
index 48ecd5b84333685325a4c49ca0d70914137681bf..6c220fc9224dd51353b12caeb6b774b4f8d3b374 100644
--- a/src/server/api/endpoints/notes/trend.ts
+++ b/src/server/api/endpoints/notes/trend.ts
@@ -2,7 +2,7 @@
  * Module dependencies
  */
 const ms = require('ms');
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note, { pack } from '../../../../models/note';
 
 /**
diff --git a/src/server/api/endpoints/notifications/get_unread_count.ts b/src/server/api/endpoints/notifications/get_unread_count.ts
index 283ecd63b14c6fa46e9ca1ef85424590d0e68017..600a80d1942ee6919696e956aeacea994241d247 100644
--- a/src/server/api/endpoints/notifications/get_unread_count.ts
+++ b/src/server/api/endpoints/notifications/get_unread_count.ts
@@ -6,10 +6,6 @@ import Mute from '../../../../models/mute';
 
 /**
  * Get count of unread notifications
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	const mute = await Mute.find({
diff --git a/src/server/api/endpoints/notifications/mark_as_read_all.ts b/src/server/api/endpoints/notifications/mark_as_read_all.ts
index 01c9145837c5e3eeceff7fa537aab3ca7b0f6ae6..dce3cb466360e51530dd00389430173de3a6bf20 100644
--- a/src/server/api/endpoints/notifications/mark_as_read_all.ts
+++ b/src/server/api/endpoints/notifications/mark_as_read_all.ts
@@ -6,10 +6,6 @@ import event from '../../../../publishers/stream';
 
 /**
  * Mark as read all notifications
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Update documents
diff --git a/src/server/api/endpoints/othello/games.ts b/src/server/api/endpoints/othello/games.ts
index d05c1c258593f61ac7dba0a0c87bb386539bb13d..3b23b606371587d5a56124d0c3b4a9c7fd73faaa 100644
--- a/src/server/api/endpoints/othello/games.ts
+++ b/src/server/api/endpoints/othello/games.ts
@@ -1,4 +1,4 @@
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import OthelloGame, { pack } from '../../../../models/othello-game';
 
 module.exports = (params, user) => new Promise(async (res, rej) => {
@@ -11,11 +11,11 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.type(ID).$;
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	const [untilId, untilIdErr] = $(params.untilId).optional.type(ID).$;
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Check if both of sinceId and untilId is specified
diff --git a/src/server/api/endpoints/othello/games/show.ts b/src/server/api/endpoints/othello/games/show.ts
index dd886936d43236f2682292fb05da7fa92503913d..d76c6556a2ac6f51f09749b61d72fd5cef7d302e 100644
--- a/src/server/api/endpoints/othello/games/show.ts
+++ b/src/server/api/endpoints/othello/games/show.ts
@@ -1,10 +1,10 @@
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import OthelloGame, { pack } from '../../../../../models/othello-game';
 import Othello from '../../../../../othello/core';
 
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'gameId' parameter
-	const [gameId, gameIdErr] = $(params.gameId).id().$;
+	const [gameId, gameIdErr] = $(params.gameId).type(ID).$;
 	if (gameIdErr) return rej('invalid gameId param');
 
 	const game = await OthelloGame.findOne({ _id: gameId });
diff --git a/src/server/api/endpoints/othello/match.ts b/src/server/api/endpoints/othello/match.ts
index d9274f8f9c5419d9702c64f402730c1a86803000..b73b64437bb1b05f65a340cc55baae805b9750b7 100644
--- a/src/server/api/endpoints/othello/match.ts
+++ b/src/server/api/endpoints/othello/match.ts
@@ -1,4 +1,4 @@
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Matching, { pack as packMatching } from '../../../../models/othello-matching';
 import OthelloGame, { pack as packGame } from '../../../../models/othello-game';
 import User from '../../../../models/user';
@@ -7,7 +7,7 @@ import { eighteight } from '../../../../othello/maps';
 
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
-	const [childId, childIdErr] = $(params.userId).id().$;
+	const [childId, childIdErr] = $(params.userId).type(ID).$;
 	if (childIdErr) return rej('invalid userId param');
 
 	// Myself
diff --git a/src/server/api/endpoints/users.ts b/src/server/api/endpoints/users.ts
index ae33e8af0c5bd8c22778dc66c7839d44068cb0e0..5b389d452f713a6de490ef0c4f6f7c15085b61ea 100644
--- a/src/server/api/endpoints/users.ts
+++ b/src/server/api/endpoints/users.ts
@@ -6,10 +6,6 @@ import User, { pack } from '../../../models/user';
 
 /**
  * Lists all users
- *
- * @param {any} params
- * @param {any} me
- * @return {Promise<any>}
  */
 module.exports = (params, me) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
diff --git a/src/server/api/endpoints/users/followers.ts b/src/server/api/endpoints/users/followers.ts
index 5f03326be856f1e1eaed9aa3933604038e9544f8..940b5ed9bce806162322dbbff0d466d2ecb4aa95 100644
--- a/src/server/api/endpoints/users/followers.ts
+++ b/src/server/api/endpoints/users/followers.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import User from '../../../../models/user';
 import Following from '../../../../models/following';
 import { pack } from '../../../../models/user';
@@ -9,14 +9,10 @@ import { getFriendIds } from '../../common/get-friends';
 
 /**
  * Get followers of a user
- *
- * @param {any} params
- * @param {any} me
- * @return {Promise<any>}
  */
 module.exports = (params, me) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
-	const [userId, userIdErr] = $(params.userId).id().$;
+	const [userId, userIdErr] = $(params.userId).type(ID).$;
 	if (userIdErr) return rej('invalid userId param');
 
 	// Get 'iknow' parameter
@@ -28,7 +24,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'cursor' parameter
-	const [cursor = null, cursorErr] = $(params.cursor).optional.id().$;
+	const [cursor = null, cursorErr] = $(params.cursor).optional.type(ID).$;
 	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 9fb135b24d57ae41ba6189020a9b5d952773b99d..63a73a2e27152379de0d2a80d7279e66c3042887 100644
--- a/src/server/api/endpoints/users/following.ts
+++ b/src/server/api/endpoints/users/following.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import User from '../../../../models/user';
 import Following from '../../../../models/following';
 import { pack } from '../../../../models/user';
@@ -16,7 +16,7 @@ import { getFriendIds } from '../../common/get-friends';
  */
 module.exports = (params, me) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
-	const [userId, userIdErr] = $(params.userId).id().$;
+	const [userId, userIdErr] = $(params.userId).type(ID).$;
 	if (userIdErr) return rej('invalid userId param');
 
 	// Get 'iknow' parameter
@@ -28,7 +28,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'cursor' parameter
-	const [cursor = null, cursorErr] = $(params.cursor).optional.id().$;
+	const [cursor = null, cursorErr] = $(params.cursor).optional.type(ID).$;
 	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 7a98f44e981ebc493345f0a91a4698bb4cf0c95b..4c00620a5215816d2003d960a85d3997ff7c3e20 100644
--- a/src/server/api/endpoints/users/get_frequently_replied_users.ts
+++ b/src/server/api/endpoints/users/get_frequently_replied_users.ts
@@ -1,13 +1,13 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note from '../../../../models/note';
 import User, { pack } from '../../../../models/user';
 
 module.exports = (params, me) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
-	const [userId, userIdErr] = $(params.userId).id().$;
+	const [userId, userIdErr] = $(params.userId).type(ID).$;
 	if (userIdErr) return rej('invalid userId param');
 
 	// Get 'limit' parameter
diff --git a/src/server/api/endpoints/users/list/create.ts b/src/server/api/endpoints/users/list/create.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6ae510f52b79dbecb36dba6e7da5652c7c67fa5e
--- /dev/null
+++ b/src/server/api/endpoints/users/list/create.ts
@@ -0,0 +1,25 @@
+/**
+ * Module dependencies
+ */
+import $ from 'cafy';
+import UserList, { pack } from '../../../../../models/user-list';
+
+/**
+ * Create a user list
+ */
+module.exports = async (params, user) => new Promise(async (res, rej) => {
+	// Get 'title' parameter
+	const [title, titleErr] = $(params.title).string().range(1, 100).$;
+	if (titleErr) return rej('invalid title param');
+
+	// insert
+	const userList = await UserList.insert({
+		createdAt: new Date(),
+		userId: user._id,
+		title: title,
+		userIds: []
+	});
+
+	// Response
+	res(await pack(userList));
+});
diff --git a/src/server/api/endpoints/users/list/push.ts b/src/server/api/endpoints/users/list/push.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/server/api/endpoints/users/notes.ts b/src/server/api/endpoints/users/notes.ts
index bd4247c79c4a5709e9862f2e65a5af4adfc47cdb..dafa18bcc967d19c690549a11bc40d21d28a14d3 100644
--- a/src/server/api/endpoints/users/notes.ts
+++ b/src/server/api/endpoints/users/notes.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import getHostLower from '../../common/get-host-lower';
 import Note, { pack } from '../../../../models/note';
 import User from '../../../../models/user';
@@ -11,7 +11,7 @@ import User from '../../../../models/user';
  */
 module.exports = (params, me) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
-	const [userId, userIdErr] = $(params.userId).optional.id().$;
+	const [userId, userIdErr] = $(params.userId).optional.type(ID).$;
 	if (userIdErr) return rej('invalid userId param');
 
 	// Get 'username' parameter
@@ -43,11 +43,11 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.type(ID).$;
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	const [untilId, untilIdErr] = $(params.untilId).optional.type(ID).$;
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Get 'sinceDate' parameter
diff --git a/src/server/api/endpoints/users/recommendation.ts b/src/server/api/endpoints/users/recommendation.ts
index f72bb04bf13f1cd005741a638e3ce762a95cf3b0..1e8ef8343297c4dc61795f24229d7e25fa54a5ee 100644
--- a/src/server/api/endpoints/users/recommendation.ts
+++ b/src/server/api/endpoints/users/recommendation.ts
@@ -2,7 +2,7 @@
  * Module dependencies
  */
 const ms = require('ms');
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import User, { pack } from '../../../../models/user';
 import { getFriendIds } from '../../common/get-friends';
 import Mute from '../../../../models/mute';
diff --git a/src/server/api/endpoints/users/search.ts b/src/server/api/endpoints/users/search.ts
index da30f47c2a6a02f01cc105d69357452ea713c9b5..faf9b901d1fc9fbfbb4a1ddd65d90388c82e3427 100644
--- a/src/server/api/endpoints/users/search.ts
+++ b/src/server/api/endpoints/users/search.ts
@@ -2,7 +2,7 @@
  * Module dependencies
  */
 import * as mongo from 'mongodb';
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import User, { pack } from '../../../../models/user';
 import config from '../../../../config';
 const escapeRegexp = require('escape-regexp');
diff --git a/src/server/api/endpoints/users/search_by_username.ts b/src/server/api/endpoints/users/search_by_username.ts
index 5f6ececff94da31901f7a97b8dde51793b539592..41a12d533250fe3b4196c60ddf99d14c6be89856 100644
--- a/src/server/api/endpoints/users/search_by_username.ts
+++ b/src/server/api/endpoints/users/search_by_username.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import User, { pack } from '../../../../models/user';
 
 /**
diff --git a/src/server/api/endpoints/users/show.ts b/src/server/api/endpoints/users/show.ts
index 7e7f5dc4886cf142372914282fa15ea8fd78e588..64adb5963b5a6ed3cf5b2878d12fb788ca534df1 100644
--- a/src/server/api/endpoints/users/show.ts
+++ b/src/server/api/endpoints/users/show.ts
@@ -1,7 +1,7 @@
 /**
  * Module dependencies
  */
-import $ from 'cafy';
+import $ from 'cafy'; import ID from '../../../../cafy-id';
 import User, { pack } from '../../../../models/user';
 import resolveRemoteUser from '../../../../remote/resolve-user';
 
@@ -14,7 +14,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 	let user;
 
 	// Get 'userId' parameter
-	const [userId, userIdErr] = $(params.userId).optional.id().$;
+	const [userId, userIdErr] = $(params.userId).optional.type(ID).$;
 	if (userIdErr) return rej('invalid userId param');
 
 	// Get 'username' parameter