diff --git a/src/server/api/endpoints/app/create.ts b/src/server/api/endpoints/app/create.ts
index 19795f1728..40da5144f6 100644
--- a/src/server/api/endpoints/app/create.ts
+++ b/src/server/api/endpoints/app/create.ts
@@ -2,31 +2,35 @@ import rndstr from 'rndstr';
 import $ from 'cafy';
 import App, { pack } from '../../../../models/app';
 import { ILocalUser } from '../../../../models/user';
+import getParams from '../../get-params';
 
 export const meta = {
-	requireCredential: false
+	requireCredential: false,
+
+	params: {
+		name: {
+			validator: $.str
+		},
+
+		description: {
+			validator: $.str
+		},
+
+		permission: {
+			validator: $.arr($.str).unique()
+		},
+
+		// TODO: Check it is valid url
+		callbackUrl: {
+			validator: $.str.optional.nullable,
+			default: null as any
+		},
+	}
 };
 
-/**
- * Create an app
- */
 export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
-	// Get 'name' parameter
-	const [name, nameErr] = $.str.get(params.name);
-	if (nameErr) return rej('invalid name param');
-
-	// Get 'description' parameter
-	const [description, descriptionErr] = $.str.get(params.description);
-	if (descriptionErr) return rej('invalid description param');
-
-	// Get 'permission' parameter
-	const [permission, permissionErr] = $.arr($.str).unique().get(params.permission);
-	if (permissionErr) return rej('invalid permission param');
-
-	// Get 'callbackUrl' parameter
-	// TODO: Check it is valid url
-	const [callbackUrl = null, callbackUrlErr] = $.str.optional.nullable.get(params.callbackUrl);
-	if (callbackUrlErr) return rej('invalid callbackUrl param');
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
 
 	// Generate secret
 	const secret = rndstr('a-zA-Z0-9', 32);
@@ -36,9 +40,9 @@ export default async (params: any, user: ILocalUser) => new Promise(async (res,
 		createdAt: new Date(),
 		userId: user && user._id,
 		name: name,
-		description: description,
-		permission: permission,
-		callbackUrl: callbackUrl,
+		description: ps.description,
+		permission: ps.permission,
+		callbackUrl: ps.callbackUrl,
 		secret: secret
 	});
 
diff --git a/src/server/api/endpoints/auth/accept.ts b/src/server/api/endpoints/auth/accept.ts
index fee68a20a6..ed1c2fa390 100644
--- a/src/server/api/endpoints/auth/accept.ts
+++ b/src/server/api/endpoints/auth/accept.ts
@@ -5,23 +5,27 @@ import App from '../../../../models/app';
 import AuthSess from '../../../../models/auth-session';
 import AccessToken from '../../../../models/access-token';
 import { ILocalUser } from '../../../../models/user';
+import getParams from '../../get-params';
 
 export const meta = {
 	requireCredential: true,
-	secure: true
+
+	secure: true,
+
+	params: {
+		token: {
+			validator: $.str
+		}
+	}
 };
 
-/**
- * Accept
- */
 export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
-	// Get 'token' parameter
-	const [token, tokenErr] = $.str.get(params.token);
-	if (tokenErr) return rej('invalid token param');
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
 
 	// Fetch token
 	const session = await AuthSess
-		.findOne({ token: token });
+		.findOne({ token: ps.token });
 
 	if (session === null) {
 		return rej('session not found');
diff --git a/src/server/api/endpoints/auth/session/generate.ts b/src/server/api/endpoints/auth/session/generate.ts
index bd1face9e3..79eb34d96a 100644
--- a/src/server/api/endpoints/auth/session/generate.ts
+++ b/src/server/api/endpoints/auth/session/generate.ts
@@ -1,26 +1,27 @@
-/**
- * Module dependencies
- */
 import * as uuid from 'uuid';
 import $ from 'cafy';
 import App from '../../../../../models/app';
 import AuthSess from '../../../../../models/auth-session';
 import config from '../../../../../config';
+import getParams from '../../../get-params';
+
+export const meta = {
+	requireCredential: false,
+
+	params: {
+		appSecret: {
+			validator: $.str
+		}
+	}
+};
 
-/**
- * Generate a session
- *
- * @param {any} params
- * @return {Promise<any>}
- */
 export default (params: any) => new Promise(async (res, rej) => {
-	// Get 'appSecret' parameter
-	const [appSecret, appSecretErr] = $.str.get(params.appSecret);
-	if (appSecretErr) return rej('invalid appSecret param');
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
 
 	// Lookup app
 	const app = await App.findOne({
-		secret: appSecret
+		secret: ps.appSecret
 	});
 
 	if (app == null) {
diff --git a/src/server/api/endpoints/auth/session/show.ts b/src/server/api/endpoints/auth/session/show.ts
index f2cbfe388e..9e7f4f52d4 100644
--- a/src/server/api/endpoints/auth/session/show.ts
+++ b/src/server/api/endpoints/auth/session/show.ts
@@ -1,18 +1,25 @@
 import $ from 'cafy';
 import AuthSess, { pack } from '../../../../../models/auth-session';
 import { ILocalUser } from '../../../../../models/user';
+import getParams from '../../../get-params';
+
+export const meta = {
+	requireCredential: false,
+
+	params: {
+		token: {
+			validator: $.str
+		}
+	}
+};
 
-/**
- * Show a session
- */
 export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
-	// Get 'token' parameter
-	const [token, tokenErr] = $.str.get(params.token);
-	if (tokenErr) return rej('invalid token param');
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
 
 	// Lookup session
 	const session = await AuthSess.findOne({
-		token: token
+		token: ps.token
 	});
 
 	if (session == null) {
diff --git a/src/server/api/endpoints/auth/session/userkey.ts b/src/server/api/endpoints/auth/session/userkey.ts
index 97f28464a5..50edf12abc 100644
--- a/src/server/api/endpoints/auth/session/userkey.ts
+++ b/src/server/api/endpoints/auth/session/userkey.ts
@@ -1,40 +1,41 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy';
 import App from '../../../../../models/app';
 import AuthSess from '../../../../../models/auth-session';
 import AccessToken from '../../../../../models/access-token';
 import { pack } from '../../../../../models/user';
+import getParams from '../../../get-params';
+
+export const meta = {
+	requireCredential: false,
+
+	params: {
+		appSecret: {
+			validator: $.str
+		},
+
+		token: {
+			validator: $.str
+		}
+	}
+};
 
-/**
- * Generate a session
- *
- * @param {any} params
- * @return {Promise<any>}
- */
 export default (params: any) => new Promise(async (res, rej) => {
-	// Get 'appSecret' parameter
-	const [appSecret, appSecretErr] = $.str.get(params.appSecret);
-	if (appSecretErr) return rej('invalid appSecret param');
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
 
 	// Lookup app
 	const app = await App.findOne({
-		secret: appSecret
+		secret: ps.appSecret
 	});
 
 	if (app == null) {
 		return rej('app not found');
 	}
 
-	// Get 'token' parameter
-	const [token, tokenErr] = $.str.get(params.token);
-	if (tokenErr) return rej('invalid token param');
-
 	// Fetch token
 	const session = await AuthSess
 		.findOne({
-			token: token,
+			token: ps.token,
 			appId: app._id
 		});
 
diff --git a/src/server/api/endpoints/drive/files/check_existence.ts b/src/server/api/endpoints/drive/files/check_existence.ts
index 407c7d5530..a5bdad5fb9 100644
--- a/src/server/api/endpoints/drive/files/check_existence.ts
+++ b/src/server/api/endpoints/drive/files/check_existence.ts
@@ -1,6 +1,7 @@
 import $ from 'cafy';
 import DriveFile, { pack } from '../../../../../models/drive-file';
 import { ILocalUser } from '../../../../../models/user';
+import getParams from '../../../get-params';
 
 export const meta = {
 	desc: {
@@ -23,11 +24,11 @@ export const meta = {
 };
 
 export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
-	const [md5, md5Err] = $.str.get(params.md5);
-	if (md5Err) return rej('invalid md5 param');
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
 
 	const file = await DriveFile.findOne({
-		md5: md5,
+		md5: ps.md5,
 		'metadata.userId': user._id,
 		'metadata.deletedAt': { $exists: false }
 	});
diff --git a/src/server/api/endpoints/i/2fa/done.ts b/src/server/api/endpoints/i/2fa/done.ts
index 6d38ca1de1..40b45a3d0b 100644
--- a/src/server/api/endpoints/i/2fa/done.ts
+++ b/src/server/api/endpoints/i/2fa/done.ts
@@ -1,18 +1,25 @@
 import $ from 'cafy';
 import * as speakeasy from 'speakeasy';
 import User, { ILocalUser } from '../../../../../models/user';
+import getParams from '../../../get-params';
 
 export const meta = {
 	requireCredential: true,
-	secure: true
+
+	secure: true,
+
+	params: {
+		token: {
+			validator: $.str
+		}
+	}
 };
 
 export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
-	// Get 'token' parameter
-	const [token, tokenErr] = $.str.get(params.token);
-	if (tokenErr) return rej('invalid token param');
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
 
-	const _token = token.replace(/\s/g, '');
+	const _token = ps.token.replace(/\s/g, '');
 
 	if (user.twoFactorTempSecret == null) {
 		return rej('二段階認証の設定が開始されていません');
diff --git a/src/server/api/endpoints/i/2fa/register.ts b/src/server/api/endpoints/i/2fa/register.ts
index 0466a4f366..4d6b05b787 100644
--- a/src/server/api/endpoints/i/2fa/register.ts
+++ b/src/server/api/endpoints/i/2fa/register.ts
@@ -4,19 +4,26 @@ import * as speakeasy from 'speakeasy';
 import * as QRCode from 'qrcode';
 import User, { ILocalUser } from '../../../../../models/user';
 import config from '../../../../../config';
+import getParams from '../../../get-params';
 
 export const meta = {
 	requireCredential: true,
-	secure: true
+
+	secure: true,
+
+	params: {
+		password: {
+			validator: $.str
+		}
+	}
 };
 
 export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
-	// Get 'password' parameter
-	const [password, passwordErr] = $.str.get(params.password);
-	if (passwordErr) return rej('invalid password param');
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
 
 	// Compare password
-	const same = await bcrypt.compare(password, user.password);
+	const same = await bcrypt.compare(ps.password, user.password);
 
 	if (!same) {
 		return rej('incorrect password');
diff --git a/src/server/api/endpoints/i/2fa/unregister.ts b/src/server/api/endpoints/i/2fa/unregister.ts
index accf3ea0f2..e3a1bd43de 100644
--- a/src/server/api/endpoints/i/2fa/unregister.ts
+++ b/src/server/api/endpoints/i/2fa/unregister.ts
@@ -1,19 +1,26 @@
 import $ from 'cafy';
 import * as bcrypt from 'bcryptjs';
 import User, { ILocalUser } from '../../../../../models/user';
+import getParams from '../../../get-params';
 
 export const meta = {
 	requireCredential: true,
-	secure: true
+
+	secure: true,
+
+	params: {
+		password: {
+			validator: $.str
+		}
+	}
 };
 
 export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
-	// Get 'password' parameter
-	const [password, passwordErr] = $.str.get(params.password);
-	if (passwordErr) return rej('invalid password param');
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
 
 	// Compare password
-	const same = await bcrypt.compare(password, user.password);
+	const same = await bcrypt.compare(ps.password, user.password);
 
 	if (!same) {
 		return rej('incorrect password');
diff --git a/src/server/api/endpoints/i/authorized_apps.ts b/src/server/api/endpoints/i/authorized_apps.ts
index 9c15670d17..09bcd2dcb6 100644
--- a/src/server/api/endpoints/i/authorized_apps.ts
+++ b/src/server/api/endpoints/i/authorized_apps.ts
@@ -2,38 +2,47 @@ import $ from 'cafy';
 import AccessToken from '../../../../models/access-token';
 import { pack } from '../../../../models/app';
 import { ILocalUser } from '../../../../models/user';
+import getParams from '../../get-params';
 
 export const meta = {
 	requireCredential: true,
-	secure: true
+
+	secure: true,
+
+	params: {
+		limit: {
+			validator: $.num.optional.range(1, 100),
+			default: 10,
+		},
+
+		offset: {
+			validator: $.num.optional.min(0),
+			default: 0,
+		},
+
+		sort: {
+			validator: $.str.optional.or('desc|asc'),
+			default: 'desc',
+		}
+	}
 };
 
 export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
-	// Get 'limit' parameter
-	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);
-	if (offsetErr) return rej('invalid offset param');
-
-	// Get 'sort' parameter
-	const [sort = 'desc', sortError] = $.str.optional.or('desc asc').get(params.sort);
-	if (sortError) return rej('invalid sort param');
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
 
 	// Get tokens
 	const tokens = await AccessToken
 		.find({
 			userId: user._id
 		}, {
-			limit: limit,
-			skip: offset,
+			limit: ps.limit,
+			skip: ps.offset,
 			sort: {
-				_id: sort == 'asc' ? 1 : -1
+				_id: ps.sort == 'asc' ? 1 : -1
 			}
 		});
 
-	// Serialize
 	res(await Promise.all(tokens.map(token => pack(token.appId, user, {
 		detail: true
 	}))));
diff --git a/src/server/api/endpoints/i/change_password.ts b/src/server/api/endpoints/i/change_password.ts
index dc0f060c08..818637e224 100644
--- a/src/server/api/endpoints/i/change_password.ts
+++ b/src/server/api/endpoints/i/change_password.ts
@@ -1,23 +1,30 @@
 import $ from 'cafy';
 import * as bcrypt from 'bcryptjs';
 import User, { ILocalUser } from '../../../../models/user';
+import getParams from '../../get-params';
 
 export const meta = {
 	requireCredential: true,
-	secure: true
+
+	secure: true,
+
+	params: {
+		currentPassword: {
+			validator: $.str
+		},
+
+		newPassword: {
+			validator: $.str
+		}
+	}
 };
 
 export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
-	// Get 'currentPasword' parameter
-	const [currentPassword, currentPasswordErr] = $.str.get(params.currentPasword);
-	if (currentPasswordErr) return rej('invalid currentPasword param');
-
-	// Get 'newPassword' parameter
-	const [newPassword, newPasswordErr] = $.str.get(params.newPassword);
-	if (newPasswordErr) return rej('invalid newPassword param');
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
 
 	// Compare password
-	const same = await bcrypt.compare(currentPassword, user.password);
+	const same = await bcrypt.compare(ps.currentPassword, user.password);
 
 	if (!same) {
 		return rej('incorrect password');
@@ -25,7 +32,7 @@ export default async (params: any, user: ILocalUser) => new Promise(async (res,
 
 	// Generate hash of password
 	const salt = await bcrypt.genSalt(8);
-	const hash = await bcrypt.hash(newPassword, salt);
+	const hash = await bcrypt.hash(ps.newPassword, salt);
 
 	await User.update(user._id, {
 		$set: {
diff --git a/src/server/api/endpoints/i/regenerate_token.ts b/src/server/api/endpoints/i/regenerate_token.ts
index 2d85f06cfa..81997362fc 100644
--- a/src/server/api/endpoints/i/regenerate_token.ts
+++ b/src/server/api/endpoints/i/regenerate_token.ts
@@ -3,19 +3,26 @@ import * as bcrypt from 'bcryptjs';
 import User, { ILocalUser } from '../../../../models/user';
 import { publishMainStream } from '../../../../stream';
 import generateUserToken from '../../common/generate-native-user-token';
+import getParams from '../../get-params';
 
 export const meta = {
 	requireCredential: true,
-	secure: true
+
+	secure: true,
+
+	params: {
+		password: {
+			validator: $.str
+		}
+	}
 };
 
 export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
-	// Get 'password' parameter
-	const [password, passwordErr] = $.str.get(params.password);
-	if (passwordErr) return rej('invalid password param');
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
 
 	// Compare password
-	const same = await bcrypt.compare(password, user.password);
+	const same = await bcrypt.compare(ps.password, user.password);
 
 	if (!same) {
 		return rej('incorrect password');
diff --git a/src/server/api/endpoints/i/update_client_setting.ts b/src/server/api/endpoints/i/update_client_setting.ts
index 2c05299dff..a1631b1d95 100644
--- a/src/server/api/endpoints/i/update_client_setting.ts
+++ b/src/server/api/endpoints/i/update_client_setting.ts
@@ -1,23 +1,30 @@
 import $ from 'cafy';
 import User, { ILocalUser } from '../../../../models/user';
 import { publishMainStream } from '../../../../stream';
+import getParams from '../../get-params';
 
 export const meta = {
 	requireCredential: true,
-	secure: true
+
+	secure: true,
+
+	params: {
+		name: {
+			validator: $.str
+		},
+
+		value: {
+			validator: $.any.nullable
+		}
+	}
 };
 
 export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
-	// Get 'name' parameter
-	const [name, nameErr] = $.str.get(params.name);
-	if (nameErr) return rej('invalid name param');
-
-	// Get 'value' parameter
-	const [value, valueErr] = $.any.nullable.get(params.value);
-	if (valueErr) return rej('invalid value param');
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
 
 	const x: any = {};
-	x[`clientSettings.${name}`] = value;
+	x[`clientSettings.${name}`] = ps.value;
 
 	await User.update(user._id, {
 		$set: x
@@ -28,6 +35,6 @@ export default async (params: any, user: ILocalUser) => new Promise(async (res,
 	// Publish event
 	publishMainStream(user._id, 'clientSettingUpdated', {
 		key: name,
-		value
+		value: ps.value
 	});
 });
diff --git a/src/server/api/endpoints/i/update_home.ts b/src/server/api/endpoints/i/update_home.ts
index 27afc9fe5a..eadd0290ab 100644
--- a/src/server/api/endpoints/i/update_home.ts
+++ b/src/server/api/endpoints/i/update_home.ts
@@ -1,29 +1,36 @@
 import $ from 'cafy';
 import User, { ILocalUser } from '../../../../models/user';
 import { publishMainStream } from '../../../../stream';
+import getParams from '../../get-params';
 
 export const meta = {
 	requireCredential: true,
-	secure: true
+
+	secure: true,
+
+	params: {
+		home: {
+			validator: $.arr($.obj({
+				name: $.str,
+				id: $.str,
+				place: $.str,
+				data: $.obj()
+			}).strict())
+		}
+	}
 };
 
 export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
-	// Get 'home' parameter
-	const [home, homeErr] = $.arr($.obj({
-		name: $.str,
-		id: $.str,
-		place: $.str,
-		data: $.obj()
-	}).strict()).get(params.home);
-	if (homeErr) return rej('invalid home param');
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
 
 	await User.update(user._id, {
 		$set: {
-			'clientSettings.home': home
+			'clientSettings.home': ps.home
 		}
 	});
 
 	res();
 
-	publishMainStream(user._id, 'homeUpdated', home);
+	publishMainStream(user._id, 'homeUpdated', ps.home);
 });
diff --git a/src/server/api/endpoints/i/update_mobile_home.ts b/src/server/api/endpoints/i/update_mobile_home.ts
index 1d4df389e4..c886574f23 100644
--- a/src/server/api/endpoints/i/update_mobile_home.ts
+++ b/src/server/api/endpoints/i/update_mobile_home.ts
@@ -1,28 +1,35 @@
 import $ from 'cafy';
 import User, { ILocalUser } from '../../../../models/user';
 import { publishMainStream } from '../../../../stream';
+import getParams from '../../get-params';
 
 export const meta = {
 	requireCredential: true,
-	secure: true
+
+	secure: true,
+
+	params: {
+		home: {
+			validator: $.arr($.obj({
+				name: $.str,
+				id: $.str,
+				data: $.obj()
+			}).strict())
+		}
+	}
 };
 
 export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
-	// Get 'home' parameter
-	const [home, homeErr] = $.arr($.obj({
-		name: $.str,
-		id: $.str,
-		data: $.obj()
-	}).strict()).get(params.home);
-	if (homeErr) return rej('invalid home param');
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
 
 	await User.update(user._id, {
 		$set: {
-			'clientSettings.mobileHome': home
+			'clientSettings.mobileHome': ps.home
 		}
 	});
 
 	res();
 
-	publishMainStream(user._id, 'mobileHomeUpdated', home);
+	publishMainStream(user._id, 'mobileHomeUpdated', ps.home);
 });
diff --git a/src/server/api/endpoints/i/update_widget.ts b/src/server/api/endpoints/i/update_widget.ts
index 92499493eb..947a29074c 100644
--- a/src/server/api/endpoints/i/update_widget.ts
+++ b/src/server/api/endpoints/i/update_widget.ts
@@ -1,31 +1,38 @@
 import $ from 'cafy';
 import User, { ILocalUser } from '../../../../models/user';
 import { publishMainStream } from '../../../../stream';
+import getParams from '../../get-params';
 
 export const meta = {
 	requireCredential: true,
-	secure: true
+
+	secure: true,
+
+	params: {
+		id: {
+			validator: $.str
+		},
+
+		data: {
+			validator: $.obj()
+		}
+	}
 };
 
 export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
-	// Get 'id' parameter
-	const [id, idErr] = $.str.get(params.id);
-	if (idErr) return rej('invalid id param');
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
 
-	// Get 'data' parameter
-	const [data, dataErr] = $.obj().get(params.data);
-	if (dataErr) return rej('invalid data param');
-
-	if (id == null && data == null) return rej('you need to set id and data params if home param unset');
+	if (ps.id == null && ps.data == null) return rej('you need to set id and data params if home param unset');
 
 	let widget;
 
 	//#region Desktop home
 	if (widget == null && user.clientSettings.home) {
 		const desktopHome = user.clientSettings.home;
-		widget = desktopHome.find((w: any) => w.id == id);
+		widget = desktopHome.find((w: any) => w.id == ps.id);
 		if (widget) {
-				widget.data = data;
+				widget.data = ps.data;
 
 			await User.update(user._id, {
 				$set: {
@@ -39,9 +46,9 @@ export default async (params: any, user: ILocalUser) => new Promise(async (res,
 	//#region Mobile home
 	if (widget == null && user.clientSettings.mobileHome) {
 		const mobileHome = user.clientSettings.mobileHome;
-		widget = mobileHome.find((w: any) => w.id == id);
+		widget = mobileHome.find((w: any) => w.id == ps.id);
 		if (widget) {
-				widget.data = data;
+				widget.data = ps.data;
 
 			await User.update(user._id, {
 				$set: {
@@ -57,11 +64,11 @@ export default async (params: any, user: ILocalUser) => new Promise(async (res,
 		const deck = user.clientSettings.deck;
 		deck.columns.filter((c: any) => c.type == 'widgets').forEach((c: any) => {
 			c.widgets.forEach((w: any) => {
-				if (w.id == id) widget = w;
+				if (w.id == ps.id) widget = w;
 			});
 		});
 		if (widget) {
-				widget.data = data;
+				widget.data = ps.data;
 
 			await User.update(user._id, {
 				$set: {
@@ -74,7 +81,7 @@ export default async (params: any, user: ILocalUser) => new Promise(async (res,
 
 	if (widget) {
 		publishMainStream(user._id, 'widgetUpdated', {
-			id, data
+			id: ps.id, data: ps.data
 		});
 
 		res();
diff --git a/src/server/api/endpoints/messaging/history.ts b/src/server/api/endpoints/messaging/history.ts
index 1dd08cd13c..078af21f27 100644
--- a/src/server/api/endpoints/messaging/history.ts
+++ b/src/server/api/endpoints/messaging/history.ts
@@ -3,6 +3,7 @@ import History from '../../../../models/messaging-history';
 import Mute from '../../../../models/mute';
 import { pack } from '../../../../models/messaging-message';
 import { ILocalUser } from '../../../../models/user';
+import getParams from '../../get-params';
 
 export const meta = {
 	desc: {
@@ -12,13 +13,19 @@ export const meta = {
 
 	requireCredential: true,
 
-	kind: 'messaging-read'
+	kind: 'messaging-read',
+
+	params: {
+		limit: {
+			validator: $.num.optional.range(1, 100),
+			default: 10
+		}
+	}
 };
 
 export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
-	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
-	if (limitErr) return rej('invalid limit param');
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
 
 	const mute = await Mute.find({
 		muterId: user._id,
@@ -33,12 +40,11 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
 				$nin: mute.map(m => m.muteeId)
 			}
 		}, {
-			limit: limit,
+			limit: ps.limit,
 			sort: {
 				updatedAt: -1
 			}
 		});
 
-	// Serialize
 	res(await Promise.all(history.map(h => pack(h.messageId, user))));
 });
diff --git a/src/server/api/endpoints/my/apps.ts b/src/server/api/endpoints/my/apps.ts
index 30c08aa09c..0b051f600c 100644
--- a/src/server/api/endpoints/my/apps.ts
+++ b/src/server/api/endpoints/my/apps.ts
@@ -1,6 +1,7 @@
 import $ from 'cafy';
 import App, { pack } from '../../../../models/app';
 import { ILocalUser } from '../../../../models/user';
+import getParams from '../../get-params';
 
 export const meta = {
 	desc: {
@@ -8,17 +9,24 @@ export const meta = {
 		'en-US': 'Get my apps'
 	},
 
-	requireCredential: true
+	requireCredential: true,
+
+	params: {
+		limit: {
+			validator: $.num.optional.range(1, 100),
+			default: 10
+		},
+
+		offset: {
+			validator: $.num.optional.min(0),
+			default: 0
+		}
+	}
 };
 
 export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
-	// Get 'limit' parameter
-	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);
-	if (offsetErr) return rej('invalid offset param');
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
 
 	const query = {
 		userId: user._id
@@ -27,8 +35,8 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
 	// Execute query
 	const apps = await App
 		.find(query, {
-			limit: limit,
-			skip: offset,
+			limit: ps.limit,
+			skip: ps.offset,
 			sort: {
 				_id: -1
 			}
diff --git a/src/server/api/endpoints/notes/polls/recommendation.ts b/src/server/api/endpoints/notes/polls/recommendation.ts
index 9af223c010..34250a32f9 100644
--- a/src/server/api/endpoints/notes/polls/recommendation.ts
+++ b/src/server/api/endpoints/notes/polls/recommendation.ts
@@ -2,6 +2,7 @@ import $ from 'cafy';
 import Vote from '../../../../../models/poll-vote';
 import Note, { pack } from '../../../../../models/note';
 import { ILocalUser } from '../../../../../models/user';
+import getParams from '../../../get-params';
 
 export const meta = {
 	desc: {
@@ -10,16 +11,23 @@ export const meta = {
 	},
 
 	requireCredential: true,
+
+	params: {
+		limit: {
+			validator: $.num.optional.range(1, 100),
+			default: 10
+		},
+
+		offset: {
+			validator: $.num.optional.min(0),
+			default: 0
+		}
+	}
 };
 
 export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
-	// Get 'limit' parameter
-	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);
-	if (offsetErr) return rej('invalid offset param');
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
 
 	// Get votes
 	const votes = await Vote.find({
@@ -46,14 +54,14 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
 				$ne: null
 			}
 		}, {
-			limit: limit,
-			skip: offset,
+			limit: ps.limit,
+			skip: ps.offset,
 			sort: {
 				_id: -1
 			}
 		});
 
-	// Serialize
-	res(await Promise.all(notes.map(async note =>
-		await pack(note, user, { detail: true }))));
+	res(await Promise.all(notes.map(note => pack(note, user, {
+		detail: true
+	}))));
 });
diff --git a/src/server/api/endpoints/notes/search.ts b/src/server/api/endpoints/notes/search.ts
index 2755a70483..63a87c0f56 100644
--- a/src/server/api/endpoints/notes/search.ts
+++ b/src/server/api/endpoints/notes/search.ts
@@ -4,19 +4,36 @@ import Note from '../../../../models/note';
 import { ILocalUser } from '../../../../models/user';
 import { packMany } from '../../../../models/note';
 import es from '../../../../db/elasticsearch';
+import getParams from '../../get-params';
+
+export const meta = {
+	desc: {
+		'ja-JP': '投稿を検索します。',
+		'en-US': 'Search notes.'
+	},
+
+	requireCredential: false,
+
+	params: {
+		query: {
+			validator: $.str
+		},
+
+		limit: {
+			validator: $.num.optional.range(1, 100),
+			default: 10
+		},
+
+		offset: {
+			validator: $.num.optional.min(0),
+			default: 0
+		}
+	}
+};
 
 export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
-	// Get 'query' parameter
-	const [query, queryError] = $.str.get(params.query);
-	if (queryError) return rej('invalid query param');
-
-	// Get 'offset' parameter
-	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);
-	if (limitErr) return rej('invalid limit param');
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
 
 	if (es == null) return rej('searching not available');
 
@@ -24,12 +41,12 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) =>
 		index: 'misskey',
 		type: 'note',
 		body: {
-			size: limit,
-			from: offset,
+			size: ps.limit,
+			from: ps.offset,
 			query: {
 				simple_query_string: {
 					fields: ['text'],
-					query: query,
+					query: ps.query,
 					default_operator: 'and'
 				}
 			},
diff --git a/src/server/api/endpoints/notes/trend.ts b/src/server/api/endpoints/notes/trend.ts
deleted file mode 100644
index 9f55ed3243..0000000000
--- a/src/server/api/endpoints/notes/trend.ts
+++ /dev/null
@@ -1,76 +0,0 @@
-const ms = require('ms');
-import $ from 'cafy';
-import Note, { pack } from '../../../../models/note';
-import { ILocalUser } from '../../../../models/user';
-
-export const meta = {
-	desc: {
-		'ja-JP': '人気の投稿の一覧を取得します。',
-		'en-US': 'Get trend notes.'
-	},
-
-	requireCredential: true
-};
-
-export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
-	// Get 'limit' parameter
-	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);
-	if (offsetErr) return rej('invalid offset param');
-
-	// Get 'reply' parameter
-	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);
-	if (renoteErr) return rej('invalid renote param');
-
-	// Get 'media' parameter
-	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);
-	if (pollErr) return rej('invalid poll param');
-
-	const query = {
-		_id: { $gte: new Date(Date.now() - ms('1days')) },
-		renoteCount: { $gt: 0 },
-		'_user.host': null
-	} as any;
-
-	if (reply != undefined) {
-		query.replyId = reply ? { $exists: true, $ne: null } : null;
-	}
-
-	if (renote != undefined) {
-		query.renoteId = renote ? { $exists: true, $ne: null } : null;
-	}
-
-	if (media != undefined) {
-		query.fileIds = media ? { $exists: true, $ne: null } : null;
-	}
-
-	if (poll != undefined) {
-		query.poll = poll ? { $exists: true, $ne: null } : null;
-	}
-
-	// Issue query
-	const notes = await Note
-		.find(query, {
-			limit: limit,
-			skip: offset,
-			sort: {
-				renoteCount: -1,
-				_id: -1
-			}
-		});
-
-	// Serialize
-	res(await Promise.all(notes.map(async note =>
-		await pack(note, user, { detail: true }))));
-});
diff --git a/src/server/api/endpoints/sw/register.ts b/src/server/api/endpoints/sw/register.ts
index 503fc94654..69337bd8c0 100644
--- a/src/server/api/endpoints/sw/register.ts
+++ b/src/server/api/endpoints/sw/register.ts
@@ -2,33 +2,36 @@ import $ from 'cafy';
 import Subscription from '../../../../models/sw-subscription';
 import { ILocalUser } from '../../../../models/user';
 import config from '../../../../config';
+import getParams from '../../get-params';
 
 export const meta = {
-	requireCredential: true
+	requireCredential: true,
+
+	params: {
+		endpoint: {
+			validator: $.str
+		},
+
+		auth: {
+			validator: $.str
+		},
+
+		publickey: {
+			validator: $.str
+		}
+	}
 };
 
-/**
- * subscribe service worker
- */
 export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
-	// Get 'endpoint' parameter
-	const [endpoint, endpointErr] = $.str.get(params.endpoint);
-	if (endpointErr) return rej('invalid endpoint param');
-
-	// Get 'auth' parameter
-	const [auth, authErr] = $.str.get(params.auth);
-	if (authErr) return rej('invalid auth param');
-
-	// Get 'publickey' parameter
-	const [publickey, publickeyErr] = $.str.get(params.publickey);
-	if (publickeyErr) return rej('invalid publickey param');
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
 
 	// if already subscribed
 	const exist = await Subscription.findOne({
 		userId: user._id,
-		endpoint: endpoint,
-		auth: auth,
-		publickey: publickey,
+		endpoint: ps.endpoint,
+		auth: ps.auth,
+		publickey: ps.publickey,
 		deletedAt: { $exists: false }
 	});
 
@@ -41,9 +44,9 @@ export default async (params: any, user: ILocalUser) => new Promise(async (res,
 
 	await Subscription.insert({
 		userId: user._id,
-		endpoint: endpoint,
-		auth: auth,
-		publickey: publickey
+		endpoint: ps.endpoint,
+		auth: ps.auth,
+		publickey: ps.publickey
 	});
 
 	res({
diff --git a/src/server/api/endpoints/username/available.ts b/src/server/api/endpoints/username/available.ts
index ff12b797ed..b61be84c3b 100644
--- a/src/server/api/endpoints/username/available.ts
+++ b/src/server/api/endpoints/username/available.ts
@@ -1,20 +1,27 @@
 import $ from 'cafy';
 import User from '../../../../models/user';
 import { validateUsername } from '../../../../models/user';
+import getParams from '../../get-params';
+
+export const meta = {
+	requireCredential: false,
+
+	params: {
+		username: {
+			validator: $.str.pipe(validateUsername)
+		}
+	}
+};
 
-/**
- * Check available username
- */
 export default async (params: any) => new Promise(async (res, rej) => {
-	// Get 'username' parameter
-	const [username, usernameError] = $.str.pipe(validateUsername).get(params.username);
-	if (usernameError) return rej('invalid username param');
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
 
 	// Get exist
 	const exist = await User
 		.count({
 			host: null,
-			usernameLower: username.toLowerCase()
+			usernameLower: ps.username.toLowerCase()
 		}, {
 			limit: 1
 		});
diff --git a/src/server/api/endpoints/users.ts b/src/server/api/endpoints/users.ts
index d7e85d3cbe..81751504e7 100644
--- a/src/server/api/endpoints/users.ts
+++ b/src/server/api/endpoints/users.ts
@@ -1,30 +1,38 @@
 import $ from 'cafy';
 import User, { pack, ILocalUser } from '../../../models/user';
+import getParams from '../get-params';
+
+export const meta = {
+	requireCredential: false,
+
+	params: {
+		limit: {
+			validator: $.num.optional.range(1, 100),
+			default: 10
+		},
+
+		offset: {
+			validator: $.num.optional.min(0),
+			default: 0
+		},
+
+		sort: {
+			validator: $.str.optional.or('+follower|-follower'),
+		}
+	}
+};
 
-/**
- * Lists all users
- */
 export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
-	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
-	if (limitErr) return rej('invalid limit param');
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
 
-	// Get 'offset' parameter
-	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);
-	if (sortError) return rej('invalid sort param');
-
-	// Construct query
 	let _sort;
-	if (sort) {
-		if (sort == '+follower') {
+	if (ps.sort) {
+		if (ps.sort == '+follower') {
 			_sort = {
 				followersCount: -1
 			};
-		} else if (sort == '-follower') {
+		} else if (ps.sort == '-follower') {
 			_sort = {
 				followersCount: 1
 			};
@@ -35,17 +43,14 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) =>
 		};
 	}
 
-	// Issue query
 	const users = await User
 		.find({
 			host: null
 		}, {
-			limit: limit,
+			limit: ps.limit,
 			sort: _sort,
-			skip: offset
+			skip: ps.offset
 		});
 
-	// Serialize
-	res(await Promise.all(users.map(async user =>
-		await pack(user, me))));
+	res(await Promise.all(users.map(user => pack(user, me))));
 });
diff --git a/src/server/api/endpoints/users/lists/create.ts b/src/server/api/endpoints/users/lists/create.ts
index ac4f957a0d..c14bb64daa 100644
--- a/src/server/api/endpoints/users/lists/create.ts
+++ b/src/server/api/endpoints/users/lists/create.ts
@@ -1,6 +1,7 @@
 import $ from 'cafy';
 import UserList, { pack } from '../../../../../models/user-list';
 import { ILocalUser } from '../../../../../models/user';
+import getParams from '../../../get-params';
 
 export const meta = {
 	desc: {
@@ -10,19 +11,24 @@ export const meta = {
 
 	requireCredential: true,
 
-	kind: 'account-write'
+	kind: 'account-write',
+
+	params: {
+		title: {
+			validator: $.str.range(1, 100)
+		}
+	}
 };
 
 export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
-	// Get 'title' parameter
-	const [title, titleErr] = $.str.range(1, 100).get(params.title);
-	if (titleErr) return rej('invalid title param');
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
 
 	// insert
 	const userList = await UserList.insert({
 		createdAt: new Date(),
 		userId: user._id,
-		title: title,
+		title: ps.title,
 		userIds: []
 	});
 
diff --git a/src/server/api/endpoints/users/recommendation.ts b/src/server/api/endpoints/users/recommendation.ts
index df85343f0f..47c809ee4c 100644
--- a/src/server/api/endpoints/users/recommendation.ts
+++ b/src/server/api/endpoints/users/recommendation.ts
@@ -5,6 +5,7 @@ import { getFriendIds } from '../../common/get-friends';
 import Mute from '../../../../models/mute';
 import * as request from 'request';
 import config from '../../../../config';
+import getParams from '../../get-params';
 
 export const meta = {
 	desc: {
@@ -13,10 +14,25 @@ export const meta = {
 
 	requireCredential: true,
 
-	kind: 'account-read'
+	kind: 'account-read',
+
+	params: {
+		limit: {
+			validator: $.num.optional.range(1, 100),
+			default: 10
+		},
+
+		offset: {
+			validator: $.num.optional.min(0),
+			default: 0
+		}
+	}
 };
 
 export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
+
 	if (config.user_recommendation && config.user_recommendation.external) {
 		const userName = me.username;
 		const hostName = config.hostname;
@@ -45,14 +61,6 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) =>
 			}
 		});
 	} else {
-		// Get 'limit' parameter
-		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);
-		if (offsetErr) return rej('invalid offset param');
-
 		// ID list of the user itself and other users who the user follows
 		const followingIds = await getFriendIds(me._id);
 
@@ -72,15 +80,13 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) =>
 				},
 				host: null
 			}, {
-				limit: limit,
-				skip: offset,
+				limit: ps.limit,
+				skip: ps.offset,
 				sort: {
 					followersCount: -1
 				}
 			});
 
-		// Serialize
-		res(await Promise.all(users.map(async user =>
-			await pack(user, me, { detail: true }))));
+		res(await Promise.all(users.map(user => pack(user, me, { detail: true }))));
 	}
 });