diff --git a/src/docs/api/endpoints/style.styl b/src/docs/api/endpoints/style.styl
index e7e32b3395..56ad291627 100644
--- a/src/docs/api/endpoints/style.styl
+++ b/src/docs/api/endpoints/style.styl
@@ -21,3 +21,20 @@
 
 	> .host
 		opacity 0.7
+
+#stability
+	padding 8px 12px
+	color #fff
+	border-radius 4px
+
+	&.deprecated
+		background #f42443
+
+	&.experimental
+		background #f2781a
+
+	&.stable
+		background #3dcc90
+
+	> b
+		margin-left 4px
diff --git a/src/docs/api/endpoints/view.pug b/src/docs/api/endpoints/view.pug
index be7e84faa1..696ec4050f 100644
--- a/src/docs/api/endpoints/view.pug
+++ b/src/docs/api/endpoints/view.pug
@@ -14,6 +14,11 @@ block main
 			| /
 		span.path= endpointUrl.path
 
+	- var stability = endpoint.stability || 'experimental';
+	p#stability(class=stability)
+		| Stability:
+		b= stability
+
 	if endpoint.desc
 		p#desc= endpoint.desc[lang] || endpoint.desc['ja-JP']
 
diff --git a/src/server/api/endpoints.ts b/src/server/api/endpoints.ts
index 2b00094269..6e5ca90c63 100644
--- a/src/server/api/endpoints.ts
+++ b/src/server/api/endpoints.ts
@@ -2,6 +2,8 @@ import * as path from 'path';
 import * as glob from 'glob';
 
 export interface IEndpointMeta {
+	stability?: 'deprecated' | 'experimental' | 'stable';
+
 	desc?: any;
 
 	params?: any;
diff --git a/src/server/api/endpoints/following/create.ts b/src/server/api/endpoints/following/create.ts
index 00aa904f08..372bad0222 100644
--- a/src/server/api/endpoints/following/create.ts
+++ b/src/server/api/endpoints/following/create.ts
@@ -3,8 +3,11 @@ const ms = require('ms');
 import User, { pack, ILocalUser } from '../../../../models/user';
 import Following from '../../../../models/following';
 import create from '../../../../services/following/create';
+import getParams from '../../get-params';
 
 export const meta = {
+	stability: 'stable',
+
 	desc: {
 		'ja-JP': '指定したユーザーをフォローします。',
 		'en-US': 'Follow a user.'
@@ -17,24 +20,32 @@ export const meta = {
 
 	requireCredential: true,
 
-	kind: 'following-write'
+	kind: 'following-write',
+
+	params: {
+		userId: $.type(ID).note({
+			desc: {
+				'ja-JP': '対象のユーザーのID',
+				'en-US': 'Target user ID'
+			}
+		})
+	}
 };
 
 export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
+
 	const follower = user;
 
-	// Get 'userId' parameter
-	const [userId, userIdErr] = $.type(ID).get(params.userId);
-	if (userIdErr) return rej('invalid userId param');
-
 	// 自分自身
-	if (user._id.equals(userId)) {
+	if (user._id.equals(ps.userId)) {
 		return rej('followee is yourself');
 	}
 
 	// Get followee
 	const followee = await User.findOne({
-		_id: userId
+		_id: ps.userId
 	}, {
 		fields: {
 			data: false,
diff --git a/src/server/api/endpoints/following/delete.ts b/src/server/api/endpoints/following/delete.ts
index cdfbf43cd1..0489c1e041 100644
--- a/src/server/api/endpoints/following/delete.ts
+++ b/src/server/api/endpoints/following/delete.ts
@@ -3,8 +3,11 @@ const ms = require('ms');
 import User, { pack, ILocalUser } from '../../../../models/user';
 import Following from '../../../../models/following';
 import deleteFollowing from '../../../../services/following/delete';
+import getParams from '../../get-params';
 
 export const meta = {
+	stability: 'stable',
+
 	desc: {
 		'ja-JP': '指定したユーザーのフォローを解除します。',
 		'en-US': 'Unfollow a user.'
@@ -17,24 +20,32 @@ export const meta = {
 
 	requireCredential: true,
 
-	kind: 'following-write'
+	kind: 'following-write',
+
+	params: {
+		userId: $.type(ID).note({
+			desc: {
+				'ja-JP': '対象のユーザーのID',
+				'en-US': 'Target user ID'
+			}
+		})
+	}
 };
 
 export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
+
 	const follower = user;
 
-	// Get 'userId' parameter
-	const [userId, userIdErr] = $.type(ID).get(params.userId);
-	if (userIdErr) return rej('invalid userId param');
-
 	// Check if the followee is yourself
-	if (user._id.equals(userId)) {
+	if (user._id.equals(ps.userId)) {
 		return rej('followee is yourself');
 	}
 
 	// Get followee
 	const followee = await User.findOne({
-		_id: userId
+		_id: ps.userId
 	}, {
 		fields: {
 			data: false,
diff --git a/src/server/api/endpoints/i.ts b/src/server/api/endpoints/i.ts
index 5aa2070650..1c488d94c6 100644
--- a/src/server/api/endpoints/i.ts
+++ b/src/server/api/endpoints/i.ts
@@ -2,6 +2,8 @@ import User, { pack, ILocalUser } from '../../../models/user';
 import { IApp } from '../../../models/app';
 
 export const meta = {
+	stability: 'stable',
+
 	desc: {
 		'ja-JP': '自分のアカウント情報を取得します。'
 	},
diff --git a/src/server/api/endpoints/i/pin.ts b/src/server/api/endpoints/i/pin.ts
index bf729ca091..44c7fe77b8 100644
--- a/src/server/api/endpoints/i/pin.ts
+++ b/src/server/api/endpoints/i/pin.ts
@@ -5,6 +5,8 @@ import { addPinned } from '../../../../services/i/pin';
 import getParams from '../../get-params';
 
 export const meta = {
+	stability: 'stable',
+
 	desc: {
 		'ja-JP': '指定した投稿をピン留めします。'
 	},
@@ -16,7 +18,8 @@ export const meta = {
 	params: {
 		noteId: $.type(ID).note({
 			desc: {
-				'ja-JP': '対象の投稿のID'
+				'ja-JP': '対象の投稿のID',
+				'en-US': 'Target note ID'
 			}
 		})
 	}
diff --git a/src/server/api/endpoints/i/unpin.ts b/src/server/api/endpoints/i/unpin.ts
index 2a81993e4b..6c20e2771d 100644
--- a/src/server/api/endpoints/i/unpin.ts
+++ b/src/server/api/endpoints/i/unpin.ts
@@ -5,6 +5,8 @@ import { removePinned } from '../../../../services/i/pin';
 import getParams from '../../get-params';
 
 export const meta = {
+	stability: 'stable',
+
 	desc: {
 		'ja-JP': '指定した投稿のピン留めを解除します。'
 	},
@@ -16,7 +18,8 @@ export const meta = {
 	params: {
 		noteId: $.type(ID).note({
 			desc: {
-				'ja-JP': '対象の投稿のID'
+				'ja-JP': '対象の投稿のID',
+				'en-US': 'Target note ID'
 			}
 		})
 	}
diff --git a/src/server/api/endpoints/meta.ts b/src/server/api/endpoints/meta.ts
index ecd5817581..4ae377ef71 100644
--- a/src/server/api/endpoints/meta.ts
+++ b/src/server/api/endpoints/meta.ts
@@ -7,6 +7,8 @@ const pkg = require('../../../../package.json');
 const client = require('../../../../built/client/meta.json');
 
 export const meta = {
+	stability: 'stable',
+
 	desc: {
 		'ja-JP': 'インスタンス情報を取得します。',
 		'en-US': 'Get the information of this instance.'
diff --git a/src/server/api/endpoints/notes/create.ts b/src/server/api/endpoints/notes/create.ts
index 96745132a3..432561da38 100644
--- a/src/server/api/endpoints/notes/create.ts
+++ b/src/server/api/endpoints/notes/create.ts
@@ -8,6 +8,8 @@ import { IApp } from '../../../../models/app';
 import getParams from '../../get-params';
 
 export const meta = {
+	stability: 'stable',
+
 	desc: {
 		'ja-JP': '投稿します。'
 	},
diff --git a/src/server/api/endpoints/notes/delete.ts b/src/server/api/endpoints/notes/delete.ts
index 2fe36897c0..160d5c4cf6 100644
--- a/src/server/api/endpoints/notes/delete.ts
+++ b/src/server/api/endpoints/notes/delete.ts
@@ -2,8 +2,11 @@ import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
 import Note from '../../../../models/note';
 import deleteNote from '../../../../services/note/delete';
 import User, { ILocalUser } from '../../../../models/user';
+import getParams from '../../get-params';
 
 export const meta = {
+	stability: 'stable',
+
 	desc: {
 		'ja-JP': '指定した投稿を削除します。',
 		'en-US': 'Delete a note.'
@@ -11,17 +14,25 @@ export const meta = {
 
 	requireCredential: true,
 
-	kind: 'note-write'
+	kind: 'note-write',
+
+	params: {
+		noteId: $.type(ID).note({
+			desc: {
+				'ja-JP': '対象の投稿のID',
+				'en-US': 'Target note ID.'
+			}
+		})
+	}
 };
 
 export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
-	// Get 'noteId' parameter
-	const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
-	if (noteIdErr) return rej('invalid noteId param');
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
 
 	// Fetch note
 	const note = await Note.findOne({
-		_id: noteId
+		_id: ps.noteId
 	});
 
 	if (note === null) {
diff --git a/src/server/api/endpoints/notes/favorites/create.ts b/src/server/api/endpoints/notes/favorites/create.ts
index 9aefb701ae..76673e248a 100644
--- a/src/server/api/endpoints/notes/favorites/create.ts
+++ b/src/server/api/endpoints/notes/favorites/create.ts
@@ -5,6 +5,8 @@ import { ILocalUser } from '../../../../../models/user';
 import getParams from '../../../get-params';
 
 export const meta = {
+	stability: 'stable',
+
 	desc: {
 		'ja-JP': '指定した投稿をお気に入りに登録します。',
 		'en-US': 'Favorite a note.'
@@ -17,7 +19,8 @@ export const meta = {
 	params: {
 		noteId: $.type(ID).note({
 			desc: {
-				'ja-JP': '対象の投稿のID'
+				'ja-JP': '対象の投稿のID',
+				'en-US': 'Target note ID.'
 			}
 		})
 	}
diff --git a/src/server/api/endpoints/notes/favorites/delete.ts b/src/server/api/endpoints/notes/favorites/delete.ts
index e42b24d324..70e1ca8ccf 100644
--- a/src/server/api/endpoints/notes/favorites/delete.ts
+++ b/src/server/api/endpoints/notes/favorites/delete.ts
@@ -2,8 +2,11 @@ import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
 import Favorite from '../../../../../models/favorite';
 import Note from '../../../../../models/note';
 import { ILocalUser } from '../../../../../models/user';
+import getParams from '../../../get-params';
 
 export const meta = {
+	stability: 'stable',
+
 	desc: {
 		'ja-JP': '指定した投稿のお気に入りを解除します。',
 		'en-US': 'Unfavorite a note.'
@@ -11,17 +14,25 @@ export const meta = {
 
 	requireCredential: true,
 
-	kind: 'favorite-write'
+	kind: 'favorite-write',
+
+	params: {
+		noteId: $.type(ID).note({
+			desc: {
+				'ja-JP': '対象の投稿のID',
+				'en-US': 'Target note ID.'
+			}
+		})
+	}
 };
 
 export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
-	// Get 'noteId' parameter
-	const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
-	if (noteIdErr) return rej('invalid noteId param');
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
 
 	// Get favoritee
 	const note = await Note.findOne({
-		_id: noteId
+		_id: ps.noteId
 	});
 
 	if (note === null) {
diff --git a/src/server/api/endpoints/notes/reactions/create.ts b/src/server/api/endpoints/notes/reactions/create.ts
index ec68f065d8..aa9ab07384 100644
--- a/src/server/api/endpoints/notes/reactions/create.ts
+++ b/src/server/api/endpoints/notes/reactions/create.ts
@@ -6,6 +6,8 @@ import { ILocalUser } from '../../../../../models/user';
 import getParams from '../../../get-params';
 
 export const meta = {
+	stability: 'stable',
+
 	desc: {
 		'ja-JP': '指定した投稿にリアクションします。',
 		'en-US': 'React to a note.'
diff --git a/src/server/api/endpoints/notes/show.ts b/src/server/api/endpoints/notes/show.ts
index 3f94eeede5..e84a948c97 100644
--- a/src/server/api/endpoints/notes/show.ts
+++ b/src/server/api/endpoints/notes/show.ts
@@ -1,18 +1,35 @@
 import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
 import Note, { pack } from '../../../../models/note';
 import { ILocalUser } from '../../../../models/user';
+import getParams from '../../get-params';
+
+export const meta = {
+	stability: 'stable',
+
+	desc: {
+		'ja-JP': '指定した投稿を取得します。',
+		'en-US': 'Get a note.'
+	},
+
+	requireCredential: false,
+
+	params: {
+		noteId: $.type(ID).note({
+			desc: {
+				'ja-JP': '対象の投稿のID',
+				'en-US': 'Target note ID.'
+			}
+		})
+	}
+};
 
-/**
- * Show a note
- */
 export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
-	// Get 'noteId' parameter
-	const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
-	if (noteIdErr) return rej('invalid noteId param');
+	const [ps, psErr] = getParams(meta, params);
+	if (psErr) return rej(psErr);
 
 	// Get note
 	const note = await Note.findOne({
-		_id: noteId
+		_id: ps.noteId
 	});
 
 	if (note === null) {