diff --git a/src/client/docs/api/endpoints/view.pug b/src/client/docs/api/endpoints/view.pug
index 24fff1b798..e046b3fc33 100644
--- a/src/client/docs/api/endpoints/view.pug
+++ b/src/client/docs/api/endpoints/view.pug
@@ -30,3 +30,9 @@ block main
 		section
 			h2= i18n('docs.api.endpoints.res')
 			+propTable(res)
+
+			if resDefs
+				each resDef in resDefs
+					section(id= resDef.name)
+						h3= resDef.name
+						+propTable(resDef.props)
diff --git a/src/client/docs/api/entities/user.yaml b/src/client/docs/api/entities/user.yaml
index cccf42f221..3328734d2b 100644
--- a/src/client/docs/api/entities/user.yaml
+++ b/src/client/docs/api/entities/user.yaml
@@ -5,169 +5,173 @@ desc:
   en: "A user."
 
 props:
-  - name: "id"
+  id:
     type: "id"
     optional: false
     desc:
       ja: "ユーザーID"
       en: "The ID of this user"
-  - name: "createdAt"
+
+  createdAt:
     type: "date"
     optional: false
     desc:
       ja: "アカウント作成日時"
       en: "The registered date of this user"
-  - name: "username"
+
+  username:
     type: "string"
     optional: false
     desc:
       ja: "ユーザー名"
       en: "The username of this user"
-  - name: "description"
+
+  description:
     type: "string"
     optional: false
     desc:
       ja: "アカウントの説明(自己紹介)"
       en: "The description of this user"
-  - name: "avatarId"
+
+  avatarId:
     type: "id(DriveFile)"
     optional: true
     desc:
       ja: "アバターのID"
       en: "The ID of the avatar of this user"
-  - name: "avatarUrl"
+
+  avatarUrl:
     type: "string"
     optional: false
     desc:
       ja: "アバターのURL"
       en: "The URL of the avatar of this user"
-  - name: "bannerId"
+
+  bannerId:
     type: "id(DriveFile)"
     optional: true
     desc:
       ja: "バナーのID"
       en: "The ID of the banner of this user"
-  - name: "bannerUrl"
+
+  bannerUrl:
     type: "string"
     optional: false
     desc:
       ja: "バナーのURL"
       en: "The URL of the banner of this user"
-  - name: "followersCount"
+
+  followersCount:
     type: "number"
     optional: false
     desc:
       ja: "フォロワーの数"
       en: "The number of the followers for this user"
-  - name: "followingCount"
+
+  followingCount:
     type: "number"
     optional: false
     desc:
       ja: "フォローしているユーザーの数"
       en: "The number of the following users for this user"
-  - name: "isFollowing"
+
+  isFollowing:
     type: "boolean"
     optional: true
     desc:
       ja: "自分がこのユーザーをフォローしているか"
-  - name: "isFollowed"
+
+  isFollowed:
     type: "boolean"
     optional: true
     desc:
       ja: "自分がこのユーザーにフォローされているか"
-  - name: "isMuted"
+
+  isMuted:
     type: "boolean"
     optional: true
     desc:
       ja: "自分がこのユーザーをミュートしているか"
       en: "Whether you muted this user"
-  - name: "notesCount"
+
+  notesCount:
     type: "number"
     optional: false
     desc:
       ja: "投稿の数"
       en: "The number of the notes of this user"
-  - name: "pinnedNote"
+
+  pinnedNote:
     type: "entity(Note)"
     optional: true
     desc:
       ja: "ピン留めされた投稿"
       en: "The pinned note of this user"
-  - name: "pinnedNoteId"
+
+  pinnedNoteId:
     type: "id(Note)"
     optional: true
     desc:
       ja: "ピン留めされた投稿のID"
       en: "The ID of the pinned note of this user"
-  - name: "driveCapacity"
+
+  driveCapacity:
     type: "number"
     optional: false
     desc:
       ja: "ドライブの容量(bytes)"
       en: "The capacity of drive of this user (bytes)"
-  - name: "host"
+
+  host:
     type: "string | null"
     optional: false
     desc:
       ja: "ホスト (例: example.com:3000)"
       en: "Host (e.g. example.com:3000)"
-  - name: "account"
+
+  twitter:
+    type: "object"
+    optional: true
+    desc:
+      ja: "連携されているTwitterアカウント情報"
+      en: "The info of the connected twitter account of this user"
+    props:
+      userId:
+        type: "string"
+        optional: false
+        desc:
+          ja: "ユーザーID"
+          en: "The user ID"
+      screenName:
+        type: "string"
+        optional: false
+        desc:
+          ja: "ユーザー名"
+          en: "The screen name of this user"
+
+  isBot:
+    type: "boolean"
+    optional: true
+    desc:
+      ja: "botか否か(自己申告であることに留意)"
+      en: "Whether is bot or not"
+
+  profile:
     type: "object"
     optional: false
     desc:
-      ja: "このサーバーにおけるアカウント"
-      en: "The account of this user on this server"
-    defName: "account"
-    def:
-      - name: "lastUsedAt"
-        type: "date"
-        optional: false
-        desc:
-          ja: "最終利用日時"
-          en: "The last used date of this user"
-      - name: "isBot"
-        type: "boolean"
+      ja: "プロフィール"
+      en: "The profile of this user"
+    props:
+      location:
+        type: "string"
         optional: true
         desc:
-          ja: "botか否か(自己申告であることに留意)"
-          en: "Whether is bot or not"
-      - name: "twitter"
-        type: "object"
+          ja: "場所"
+          en: "The location of this user"
+      birthday:
+        type: "string"
         optional: true
         desc:
-          ja: "連携されているTwitterアカウント情報"
-          en: "The info of the connected twitter account of this user"
-        defName: "twitter"
-        def:
-          - name: "userId"
-            type: "string"
-            optional: false
-            desc:
-              ja: "ユーザーID"
-              en: "The user ID"
-          - name: "screenName"
-            type: "string"
-            optional: false
-            desc:
-              ja: "ユーザー名"
-              en: "The screen name of this user"
-      - name: "profile"
-        type: "object"
-        optional: false
-        desc:
-          ja: "プロフィール"
-          en: "The profile of this user"
-        defName: "profile"
-        def:
-          - name: "location"
-            type: "string"
-            optional: true
-            desc:
-              ja: "場所"
-              en: "The location of this user"
-          - name: "birthday"
-            type: "string"
-            optional: true
-            desc:
-              ja: "誕生日 (YYYY-MM-DD)"
-              en: "The birthday of this user (YYYY-MM-DD)"
+          ja: "誕生日 (YYYY-MM-DD)"
+          en: "The birthday of this user (YYYY-MM-DD)"
diff --git a/src/client/docs/api/entities/view.pug b/src/client/docs/api/entities/view.pug
index a930f71eb6..3f50bfd3bd 100644
--- a/src/client/docs/api/entities/view.pug
+++ b/src/client/docs/api/entities/view.pug
@@ -17,4 +17,4 @@ block main
 			each propDef in propDefs
 				section(id= propDef.name)
 					h3= propDef.name
-					+propTable(propDef.params)
+					+propTable(propDef.props)
diff --git a/src/client/docs/api/mixins.pug b/src/client/docs/api/mixins.pug
index 79665a61e3..9e03abefeb 100644
--- a/src/client/docs/api/mixins.pug
+++ b/src/client/docs/api/mixins.pug
@@ -22,9 +22,9 @@ mixin propTable(props)
 							a(href=`/docs/${lang}/api/entities/${kebab(prop.entity)}`)= prop.entity
 							| )
 						else if prop.kind == 'object'
-							if prop.def
+							if prop.hasDef
 								|  (
-								a(href=`#${prop.defName}`)= prop.defName
+								a(href=`#${prop.name}`)= prop.name
 								| )
 						else if prop.kind == 'date'
 							|  (Date)
diff --git a/src/server/api/endpoints/notes/create.ts b/src/server/api/endpoints/notes/create.ts
index 45fc77503e..c2f128527e 100644
--- a/src/server/api/endpoints/notes/create.ts
+++ b/src/server/api/endpoints/notes/create.ts
@@ -90,7 +90,7 @@ export const meta = {
 
 	res: {
 		type: 'object',
-		object: {
+		props: {
 			createdNote: {
 				type: 'entity(Note)',
 				desc: {
diff --git a/src/server/web/docs.ts b/src/server/web/docs.ts
index e670709634..ceba14bd27 100644
--- a/src/server/web/docs.ts
+++ b/src/server/web/docs.ts
@@ -63,66 +63,64 @@ async function genVars(lang: string): Promise<{ [key: string]: any }> {
 }
 
 // WIP type
-const parseEPDefParam = (key: string, param: Context) => {
+const parseParamDefinition = (key: string, param: Context) => {
 	return Object.assign({
 		name: key,
 		type: param.getType()
 	}, param.data);
 };
 
-const parseParam = (param: any) => {
-	const id = param.type.match(/^id\((.+?)\)|^id/);
-	const entity = param.type.match(/^entity\((.+?)\)/);
-	const isObject = /^object/.test(param.type);
-	const isDate = /^date/.test(param.type);
-	const isArray = /\[\]$/.test(param.type);
+const parsePropDefinition = (key: string, prop: any) => {
+	const id = prop.type.match(/^id\((.+?)\)|^id/);
+	const entity = prop.type.match(/^entity\((.+?)\)/);
+	const isObject = /^object/.test(prop.type);
+	const isDate = /^date/.test(prop.type);
+	const isArray = /\[\]$/.test(prop.type);
 	if (id) {
-		param.kind = 'id';
-		param.type = 'string';
-		param.entity = id[1];
+		prop.kind = 'id';
+		prop.type = 'string';
+		prop.entity = id[1];
 		if (isArray) {
-			param.type += '[]';
+			prop.type += '[]';
 		}
 	}
 	if (entity) {
-		param.kind = 'entity';
-		param.type = 'object';
-		param.entity = entity[1];
+		prop.kind = 'entity';
+		prop.type = 'object';
+		prop.entity = entity[1];
 		if (isArray) {
-			param.type += '[]';
+			prop.type += '[]';
 		}
 	}
 	if (isObject) {
-		param.kind = 'object';
+		prop.kind = 'object';
+		if (prop.props) {
+			prop.hasDef = true;
+		}
 	}
 	if (isDate) {
-		param.kind = 'date';
-		param.type = 'string';
+		prop.kind = 'date';
+		prop.type = 'string';
 		if (isArray) {
-			param.type += '[]';
+			prop.type += '[]';
 		}
 	}
 
-	if (param.optional) {
-		param.type += '?';
+	if (prop.optional) {
+		prop.type += '?';
 	}
 
-	return param;
+	prop.name = key;
+
+	return prop;
 };
 
 const sortParams = (params: Array<{name: string}>) => {
-	params.sort((a, b) => {
-		if (a.name < b.name)
-			return -1;
-		if (a.name > b.name)
-			return 1;
-		return 0;
-	});
 	return params;
 };
 
 // WIP type
-const extractEPDefs = (params: Context[]) => {
+const extractParamDefRef = (params: Context[]) => {
 	let defs: any[] = [];
 
 	params.forEach(param => {
@@ -130,10 +128,10 @@ const extractEPDefs = (params: Context[]) => {
 			const props = (param as ObjectContext<any>).props;
 			defs.push({
 				name: param.data.ref,
-				params: sortParams(Object.keys(props).map(k => parseEPDefParam(k, props[k])))
+				params: sortParams(Object.keys(props).map(k => parseParamDefinition(k, props[k])))
 			});
 
-			const childDefs = extractEPDefs(Object.keys(props).map(k => props[k]));
+			const childDefs = extractParamDefRef(Object.keys(props).map(k => props[k]));
 
 			defs = defs.concat(childDefs);
 		}
@@ -142,17 +140,17 @@ const extractEPDefs = (params: Context[]) => {
 	return sortParams(defs);
 };
 
-const extractDefs = (params: any[]) => {
+const extractPropDefRef = (props: any[]) => {
 	let defs: any[] = [];
 
-	params.forEach(param => {
-		if (param.def) {
+	Object.entries(props).forEach(([k, v]) => {
+		if (v.props) {
 			defs.push({
-				name: param.defName,
-				params: sortParams(param.def.map((p: any) => parseParam(p)))
+				name: k,
+				props: sortParams(Object.entries(v.props).map(([k, v]) => parsePropDefinition(k, v)))
 			});
 
-			const childDefs = extractDefs(param.def);
+			const childDefs = extractPropDefRef(v.props);
 
 			defs = defs.concat(childDefs);
 		}
@@ -184,8 +182,10 @@ router.get('/*/api/endpoints/*', async ctx => {
 		},
 		desc: ep.desc,
 		// @ts-ignore
-		params: sortParams(Object.keys(ep.params).map(k => parseEPDefParam(k, ep.params[k]))),
-		paramDefs: extractEPDefs(Object.keys(ep.params).map(k => ep.params[k])),
+		params: sortParams(Object.entries(ep.params).map(([k, v]) => parseParamDefinition(k, v))),
+		paramDefs: extractParamDefRef(Object.entries(ep.params).map(([k, v]) => v)),
+		res: ep.res.props ? sortParams(Object.entries(ep.res.props).map(([k, v]) => parsePropDefinition(k, v))) : null,
+		resDefs: null//extractPropDefRef(Object.entries(ep.res.props).map(([k, v]) => parsePropDefinition(k, v)))
 	};
 
 	await ctx.render('../../../../src/client/docs/api/endpoints/view', Object.assign(await genVars(lang), vars));
@@ -200,8 +200,8 @@ router.get('/*/api/entities/*', async ctx => {
 	await ctx.render('../../../../src/client/docs/api/entities/view', Object.assign(await genVars(lang), {
 		name: x.name,
 		desc: x.desc,
-		props: sortParams(x.props.map((p: any) => parseParam(p))),
-		propDefs: extractDefs(x.props)
+		props: sortParams(Object.entries(x.props).map(([k, v]) => parsePropDefinition(k, v))),
+		propDefs: extractPropDefRef(x.props)
 	}));
 });