diff --git a/locales/ja.yml b/locales/ja.yml
index cb09b84467..22514db507 100644
--- a/locales/ja.yml
+++ b/locales/ja.yml
@@ -1104,6 +1104,9 @@ docs:
       has-limit: "レートリミットがあります。"
       duration-limit: "直近{duration}ミリ秒の間のこのエンドポイントへのリクエスト数の合計が{max}を超える場合はリクエストできません。"
       min-interval-limit: "前回のリクエストから{interval}ミリ秒経っていない場合はリクエストできません。"
+      show-src: "このエンドポイントのソースコードも閲覧できます。"
+      show-src-link: "コードをGitHubで見る"
+      generated: "このドキュメントはAPI定義に基づき自動生成されています。"
     props:
       name: "名前"
       type: "型"
diff --git a/src/docs/api/endpoints/view.pug b/src/docs/api/endpoints/view.pug
index b8955511f1..4a11c4cd02 100644
--- a/src/docs/api/endpoints/view.pug
+++ b/src/docs/api/endpoints/view.pug
@@ -47,10 +47,23 @@ block main
 	if res
 		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)
+			if resProps
+				+propTable(resProps)
+
+				if resDefs
+					each resDef in resDefs
+						section(id= resDef.name)
+							h3= resDef.name
+							+propTable(resDef.props)
+			else
+				if res.type.startsWith('entity')
+					a(href=`/docs/${lang}/api/entities/${kebab(res.entity)}`)= res.entity
+
+block footer
+	div.ui.info: p
+		i.fas.fa-info-circle(style="margin-right: 4px")
+		= i18n('docs.api.endpoints.generated')
+	p
+		= i18n('docs.api.endpoints.show-src')
+		a(href=src target="_blank")= i18n('docs.api.endpoints.show-src-link')
diff --git a/src/docs/api/mixins.pug b/src/docs/api/mixins.pug
index 9e03abefeb..925aab2934 100644
--- a/src/docs/api/mixins.pug
+++ b/src/docs/api/mixins.pug
@@ -1,3 +1,24 @@
+mixin type(prop)
+	i= prop.type
+	if prop.kind == 'id'
+		if prop.entity
+			|  (
+			a(href=`/docs/${lang}/api/entities/${kebab(prop.entity)}`)= prop.entity
+			|  ID)
+		else
+			|  (ID)
+	else if prop.kind == 'entity'
+		|   (
+		a(href=`/docs/${lang}/api/entities/${kebab(prop.entity)}`)= prop.entity
+		| )
+	else if prop.kind == 'object'
+		if prop.hasDef
+			|  (
+			a(href=`#${prop.name}`)= prop.name
+			| )
+	else if prop.kind == 'date'
+		|  (Date)
+
 mixin propTable(props)
 	table.props
 		thead: tr
@@ -9,23 +30,5 @@ mixin propTable(props)
 				tr
 					td.name= prop.name
 					td.type
-						i= prop.type
-						if prop.kind == 'id'
-							if prop.entity
-								|  (
-								a(href=`/docs/${lang}/api/entities/${kebab(prop.entity)}`)= prop.entity
-								|  ID)
-							else
-								|  (ID)
-						else if prop.kind == 'entity'
-							|   (
-							a(href=`/docs/${lang}/api/entities/${kebab(prop.entity)}`)= prop.entity
-							| )
-						else if prop.kind == 'object'
-							if prop.hasDef
-								|  (
-								a(href=`#${prop.name}`)= prop.name
-								| )
-						else if prop.kind == 'date'
-							|  (Date)
+						+type(prop)
 					td.desc!= prop.desc ? prop.desc[lang] || prop.desc['ja'] : null
diff --git a/src/docs/article.pug b/src/docs/article.pug
index cba9fc6665..38494fec6c 100644
--- a/src/docs/article.pug
+++ b/src/docs/article.pug
@@ -2,3 +2,8 @@ extends ./base
 
 block main
 	!= html
+
+block footer
+	p
+		= i18n('docs.edit-this-page-on-github')
+		a(href=src target="_blank")= i18n('docs.edit-this-page-on-github-link')
diff --git a/src/docs/base.pug b/src/docs/base.pug
index 43de9b9cf7..b67fd630c4 100644
--- a/src/docs/base.pug
+++ b/src/docs/base.pug
@@ -35,7 +35,5 @@ html(lang= lang)
 					| !{content}
 
 			footer
-				p
-					| %i18n:docs.edit-this-page-on-github%
-					a(href=src target="_blank") %i18n:docs.edit-this-page-on-github-link%
+				block footer
 				small= copyright
diff --git a/src/docs/style.styl b/src/docs/style.styl
index cb74f20159..33c461a724 100644
--- a/src/docs/style.styl
+++ b/src/docs/style.styl
@@ -44,6 +44,7 @@ main
 		border-top solid 2px #eee
 
 		> small
+			display block
 			margin 16px 0 0 0
 			color #aaa
 
diff --git a/src/server/api/endpoints/i.ts b/src/server/api/endpoints/i.ts
index 8219100d60..7f25c07957 100644
--- a/src/server/api/endpoints/i.ts
+++ b/src/server/api/endpoints/i.ts
@@ -8,7 +8,12 @@ export const meta = {
 
 	requireCredential: true,
 
-	params: {}
+	params: {},
+
+	res: {
+		type: 'entity',
+		entity: 'User'
+	}
 };
 
 export default (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => {
diff --git a/src/server/web/docs.ts b/src/server/web/docs.ts
index 233178eee2..59899c078e 100644
--- a/src/server/web/docs.ts
+++ b/src/server/web/docs.ts
@@ -182,8 +182,10 @@ router.get('/*/api/endpoints/*', async ctx => {
 		// @ts-ignore
 		params: ep.meta.params ? sortParams(Object.entries(ep.meta.params).map(([k, v]) => parseParamDefinition(k, v))) : null,
 		paramDefs: ep.meta.params ? extractParamDefRef(Object.entries(ep.meta.params).map(([k, v]) => v)) : null,
-		res: ep.meta.res && ep.meta.res.props ? sortParams(Object.entries(ep.meta.res.props).map(([k, v]) => parsePropDefinition(k, v))) : null,
-		resDefs: null//extractPropDefRef(Object.entries(ep.res.props).map(([k, v]) => parsePropDefinition(k, v)))
+		res: ep.meta.res,
+		resProps: ep.meta.res && ep.meta.res.props ? sortParams(Object.entries(ep.meta.res.props).map(([k, v]) => parsePropDefinition(k, v))) : null,
+		resDefs: null,//extractPropDefRef(Object.entries(ep.res.props).map(([k, v]) => parsePropDefinition(k, v)))
+		src: `https://github.com/syuilo/misskey/tree/master/src/server/api/endpoints/${name}.ts`
 	};
 
 	await ctx.render('../../../../src/docs/api/endpoints/view', Object.assign(await genVars(lang), vars));
@@ -227,7 +229,8 @@ router.get('/*/*', async ctx => {
 
 	await ctx.render('../../../../src/docs/article', Object.assign({
 		html: conv.makeHtml(md),
-		title: md.match(/^# (.+?)\r?\n/)[1]
+		title: md.match(/^# (.+?)\r?\n/)[1],
+		src: `https://github.com/syuilo/misskey/tree/master/src/docs/${doc}.${lang}.md`
 	}, await genVars(lang)));
 });