diff --git a/package.json b/package.json
index 61ace88c1cfa31f1591fb1ccd77fad6a7c0a4375..b71b41336931460072819bfaa371908cfadf1d4c 100644
--- a/package.json
+++ b/package.json
@@ -29,7 +29,6 @@
 		"@fortawesome/free-solid-svg-icons": "5.7.2",
 		"@fortawesome/vue-fontawesome": "0.1.5",
 		"@koa/cors": "2.2.3",
-		"@prezzemolo/rap": "0.1.2",
 		"@prezzemolo/zip": "0.0.3",
 		"@types/bcryptjs": "2.4.2",
 		"@types/bull": "3.5.11",
diff --git a/src/client/app/common/views/components/user-list-editor.vue b/src/client/app/common/views/components/user-list-editor.vue
index 8d2e04d045b30522f52c909f316d6983b61c2e04..86024c4da3e6bf10d546fe72137d43000f4fe0df 100644
--- a/src/client/app/common/views/components/user-list-editor.vue
+++ b/src/client/app/common/views/components/user-list-editor.vue
@@ -77,11 +77,11 @@ export default Vue.extend({
 				input: {
 					default: this.list.name
 				}
-			}).then(({ canceled, result: title }) => {
+			}).then(({ canceled, result: name }) => {
 				if (canceled) return;
 				this.$root.api('users/lists/update', {
 					listId: this.list.id,
-					title: title
+					name: name
 				});
 			});
 		},
diff --git a/src/client/app/common/views/components/user-lists.vue b/src/client/app/common/views/components/user-lists.vue
index 786a6766d3eb32fe20529e58692061082633843f..699251b3131e80d78dd1656974b3dc80ac0a5ce7 100644
--- a/src/client/app/common/views/components/user-lists.vue
+++ b/src/client/app/common/views/components/user-lists.vue
@@ -28,10 +28,10 @@ export default Vue.extend({
 			this.$root.dialog({
 				title: this.$t('list-name'),
 				input: true
-			}).then(async ({ canceled, result: title }) => {
+			}).then(async ({ canceled, result: name }) => {
 				if (canceled) return;
 				const list = await this.$root.api('users/lists/create', {
-					title
+					name
 				});
 
 				this.lists.push(list)
diff --git a/src/client/app/desktop/views/home/timeline.vue b/src/client/app/desktop/views/home/timeline.vue
index 1e6abac823e801386d4dc2c3f50466d60f89f207..3f9681a047504d59ddd76f19003a060e1c30863e 100644
--- a/src/client/app/desktop/views/home/timeline.vue
+++ b/src/client/app/desktop/views/home/timeline.vue
@@ -123,10 +123,10 @@ export default Vue.extend({
 					this.$root.dialog({
 						title: this.$t('list-name'),
 						input: true
-					}).then(async ({ canceled, result: title }) => {
+					}).then(async ({ canceled, result: name }) => {
 						if (canceled) return;
 						const list = await this.$root.api('users/lists/create', {
-							title
+							name
 						});
 
 						this.list = list;
diff --git a/src/misc/schema.ts b/src/misc/schema.ts
index 7c17953d97cff8a2685bf42b71689bf20da28453..442c95ad988102685feacb084eca88cdefe10b79 100644
--- a/src/misc/schema.ts
+++ b/src/misc/schema.ts
@@ -1,14 +1,46 @@
+export const types = {
+	boolean: 'boolean' as 'boolean',
+	string: 'string' as 'string',
+	number: 'number' as 'number',
+	array: 'array' as 'array',
+	object: 'object' as 'object',
+	any: 'any' as 'any',
+};
+
+export const bool = {
+	true: true as true,
+	false: false as false,
+};
+
 export type Schema = {
-	type: 'number' | 'string' | 'array' | 'object' | any;
-	optional?: boolean;
+	type: 'boolean' | 'number' | 'string' | 'array' | 'object' | 'any';
+	nullable: boolean;
+	optional: boolean;
 	items?: Schema;
 	properties?: Obj;
 	description?: string;
+	example?: any;
+	format?: string;
+	ref?: string;
+	enum?: string[];
 };
 
+type NonUndefinedPropertyNames<T extends Obj> = {
+	[K in keyof T]: T[K]['optional'] extends true ? never : K
+}[keyof T];
+
+type UndefinedPropertyNames<T extends Obj> = {
+	[K in keyof T]: T[K]['optional'] extends true ? K : never
+}[keyof T];
+
+type OnlyRequired<T extends Obj> = Pick<T, NonUndefinedPropertyNames<T>>;
+type OnlyOptional<T extends Obj> = Pick<T, UndefinedPropertyNames<T>>;
+
 export type Obj = { [key: string]: Schema };
 
-export type ObjType<s extends Obj> = { [P in keyof s]: SchemaType<s[P]> };
+export type ObjType<s extends Obj> =
+	{ [P in keyof OnlyOptional<s>]?: SchemaType<s[P]> } &
+	{ [P in keyof OnlyRequired<s>]: SchemaType<s[P]> };
 
 // https://qiita.com/hrsh7th@github/items/84e8968c3601009cdcf2
 type MyType<T extends Schema> = {
@@ -16,26 +48,20 @@ type MyType<T extends Schema> = {
 	1: SchemaType<T>;
 }[T extends Schema ? 1 : 0];
 
+type NullOrUndefined<p extends Schema, T> =
+	p['nullable'] extends true
+		?	p['optional'] extends true
+			? (T | null | undefined)
+			: (T | null)
+		: p['optional'] extends true
+			? (T | undefined)
+			: T;
+
 export type SchemaType<p extends Schema> =
-	p['type'] extends 'number' ? number :
-	p['type'] extends 'string' ? string :
-	p['type'] extends 'array' ? MyType<NonNullable<p['items']>>[] :
-	p['type'] extends 'object' ? ObjType<NonNullable<p['properties']>> :
+	p['type'] extends 'number' ? NullOrUndefined<p, number> :
+	p['type'] extends 'string' ? NullOrUndefined<p, string> :
+	p['type'] extends 'boolean' ? NullOrUndefined<p, boolean> :
+	p['type'] extends 'array' ? NullOrUndefined<p, MyType<NonNullable<p['items']>>[]> :
+	p['type'] extends 'object' ? NullOrUndefined<p, ObjType<NonNullable<p['properties']>>> :
+	p['type'] extends 'any' ? NullOrUndefined<p, any> :
 	any;
-
-export function convertOpenApiSchema(schema: Schema) {
-	const x = JSON.parse(JSON.stringify(schema)); // copy
-	if (!['string', 'number', 'boolean', 'array', 'object'].includes(x.type)) {
-		x['$ref'] = `#/components/schemas/${x.type}`;
-	}
-	if (x.type === 'array' && x.items) {
-		x.items = convertOpenApiSchema(x.items);
-	}
-	if (x.type === 'object' && x.properties) {
-		x.required = Object.entries(x.properties).filter(([k, v]: any) => !v.isOptional).map(([k, v]: any) => k);
-		for (const k of Object.keys(x.properties)) {
-			x.properties[k] = convertOpenApiSchema(x.properties[k]);
-		}
-	}
-	return x;
-}
diff --git a/src/models/repositories/abuse-user-report.ts b/src/models/repositories/abuse-user-report.ts
index f619d6e37f3b02cd219ba9fed0f5020debc0a3ec..c708b265a6e8984454cf534292a62fdea07097bd 100644
--- a/src/models/repositories/abuse-user-report.ts
+++ b/src/models/repositories/abuse-user-report.ts
@@ -1,8 +1,8 @@
 import { EntityRepository, Repository } from 'typeorm';
 import { Users } from '..';
-import rap from '@prezzemolo/rap';
 import { AbuseUserReport } from '../entities/abuse-user-report';
 import { ensure } from '../../prelude/ensure';
+import { awaitAll } from '../../prelude/await-all';
 
 @EntityRepository(AbuseUserReport)
 export class AbuseUserReportRepository extends Repository<AbuseUserReport> {
@@ -17,7 +17,7 @@ export class AbuseUserReportRepository extends Repository<AbuseUserReport> {
 	) {
 		const report = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 
-		return await rap({
+		return await awaitAll({
 			id: report.id,
 			createdAt: report.createdAt,
 			reporterId: report.reporterId,
diff --git a/src/models/repositories/app.ts b/src/models/repositories/app.ts
index fa5ebf2ac76356ce4fc489b7b9937b70dbc04b2d..6562a470be698f71ca38317672b9feda345da597 100644
--- a/src/models/repositories/app.ts
+++ b/src/models/repositories/app.ts
@@ -2,6 +2,9 @@ import { EntityRepository, Repository } from 'typeorm';
 import { App } from '../entities/app';
 import { AccessTokens } from '..';
 import { ensure } from '../../prelude/ensure';
+import { types, bool, SchemaType } from '../../misc/schema';
+
+export type PackedApp = SchemaType<typeof packedAppSchema>;
 
 @EntityRepository(App)
 export class AppRepository extends Repository<App> {
@@ -13,7 +16,7 @@ export class AppRepository extends Repository<App> {
 			includeSecret?: boolean,
 			includeProfileImageIds?: boolean
 		}
-	) {
+	): Promise<PackedApp> {
 		const opts = Object.assign({
 			detail: false,
 			includeSecret: false,
@@ -37,3 +40,40 @@ export class AppRepository extends Repository<App> {
 		};
 	}
 }
+
+export const packedAppSchema = {
+	type: types.object,
+	optional: bool.false, nullable: bool.false,
+	properties: {
+		id: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'id',
+			description: 'The unique identifier for this Note.',
+			example: 'xxxxxxxxxx',
+		},
+		name: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			description: 'アプリケーションの名前'
+		},
+		callbackUrl: {
+			type: types.string,
+			optional: bool.false, nullable: bool.true,
+			description: 'コールバックするURL'
+		},
+		permission: {
+			type: types.array,
+			optional: bool.true, nullable: bool.false,
+			items: {
+				type: types.string,
+				optional: bool.false, nullable: bool.false,
+			}
+		},
+		secret: {
+			type: types.string,
+			optional: bool.true, nullable: bool.false,
+			description: 'アプリケーションのシークレットキー'
+		}
+	},
+};
diff --git a/src/models/repositories/auth-session.ts b/src/models/repositories/auth-session.ts
index 32f7968233359b7f585c56fca889bd250415e7c4..a6a4d46de641f9b89fb2ffffefa9d516aa2e7363 100644
--- a/src/models/repositories/auth-session.ts
+++ b/src/models/repositories/auth-session.ts
@@ -1,8 +1,8 @@
 import { EntityRepository, Repository } from 'typeorm';
 import { Apps } from '..';
-import rap from '@prezzemolo/rap';
 import { AuthSession } from '../entities/auth-session';
 import { ensure } from '../../prelude/ensure';
+import { awaitAll } from '../../prelude/await-all';
 
 @EntityRepository(AuthSession)
 export class AuthSessionRepository extends Repository<AuthSession> {
@@ -12,7 +12,7 @@ export class AuthSessionRepository extends Repository<AuthSession> {
 	) {
 		const session = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 
-		return await rap({
+		return await awaitAll({
 			id: session.id,
 			app: Apps.pack(session.appId, me),
 			token: session.token
diff --git a/src/models/repositories/blocking.ts b/src/models/repositories/blocking.ts
index e18aa591f371292a5b7399dfc34376c5198d87d6..fd209bce1c632f79b7f607688f481ef3f34c3540 100644
--- a/src/models/repositories/blocking.ts
+++ b/src/models/repositories/blocking.ts
@@ -1,8 +1,11 @@
 import { EntityRepository, Repository } from 'typeorm';
 import { Users } from '..';
-import rap from '@prezzemolo/rap';
 import { Blocking } from '../entities/blocking';
 import { ensure } from '../../prelude/ensure';
+import { awaitAll } from '../../prelude/await-all';
+import { SchemaType, types, bool } from '../../misc/schema';
+
+export type PackedBlocking = SchemaType<typeof packedBlockingSchema>;
 
 @EntityRepository(Blocking)
 export class BlockingRepository extends Repository<Blocking> {
@@ -16,14 +19,47 @@ export class BlockingRepository extends Repository<Blocking> {
 	public async pack(
 		src: Blocking['id'] | Blocking,
 		me?: any
-	) {
+	): Promise<PackedBlocking> {
 		const blocking = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 
-		return await rap({
+		return await awaitAll({
 			id: blocking.id,
+			createdAt: blocking.createdAt.toISOString(),
+			blockeeId: blocking.blockeeId,
 			blockee: Users.pack(blocking.blockeeId, me, {
 				detail: true
 			})
 		});
 	}
 }
+
+export const packedBlockingSchema = {
+	type: types.object,
+	optional: bool.false, nullable: bool.false,
+	properties: {
+		id: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'id',
+			description: 'The unique identifier for this blocking.',
+			example: 'xxxxxxxxxx',
+		},
+		createdAt: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'date-time',
+			description: 'The date that the blocking was created.'
+		},
+		blockeeId: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'id',
+		},
+		blockee: {
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'User',
+			description: 'The blockee.'
+		},
+	}
+};
diff --git a/src/models/repositories/drive-file.ts b/src/models/repositories/drive-file.ts
index f117b38b24a2df60b13a43130e071839e4868eae..245db4b797db5ce7f66c7334b8ff905600e3c07e 100644
--- a/src/models/repositories/drive-file.ts
+++ b/src/models/repositories/drive-file.ts
@@ -1,10 +1,13 @@
 import { EntityRepository, Repository } from 'typeorm';
 import { DriveFile } from '../entities/drive-file';
 import { Users, DriveFolders } from '..';
-import rap from '@prezzemolo/rap';
 import { User } from '../entities/user';
 import { toPuny } from '../../misc/convert-host';
 import { ensure } from '../../prelude/ensure';
+import { awaitAll } from '../../prelude/await-all';
+import { types, bool, SchemaType } from '../../misc/schema';
+
+export type PackedDriveFile = SchemaType<typeof packedDriveFileSchema>;
 
 @EntityRepository(DriveFile)
 export class DriveFileRepository extends Repository<DriveFile> {
@@ -82,7 +85,7 @@ export class DriveFileRepository extends Repository<DriveFile> {
 			self?: boolean,
 			withUser?: boolean,
 		}
-	) {
+	): Promise<PackedDriveFile> {
 		const opts = Object.assign({
 			detail: false,
 			self: false
@@ -90,9 +93,9 @@ export class DriveFileRepository extends Repository<DriveFile> {
 
 		const file = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 
-		return await rap({
+		return await awaitAll({
 			id: file.id,
-			createdAt: file.createdAt,
+			createdAt: file.createdAt.toISOString(),
 			name: file.name,
 			type: file.type,
 			md5: file.md5,
@@ -109,3 +112,66 @@ export class DriveFileRepository extends Repository<DriveFile> {
 		});
 	}
 }
+
+export const packedDriveFileSchema = {
+	type: types.object,
+	optional: bool.false, nullable: bool.false,
+	properties: {
+		id: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'id',
+			description: 'The unique identifier for this Drive file.',
+			example: 'xxxxxxxxxx',
+		},
+		createdAt: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'date-time',
+			description: 'The date that the Drive file was created on Misskey.'
+		},
+		name: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			description: 'The file name with extension.',
+			example: 'lenna.jpg'
+		},
+		type: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			description: 'The MIME type of this Drive file.',
+			example: 'image/jpeg'
+		},
+		md5: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'md5',
+			description: 'The MD5 hash of this Drive file.',
+			example: '15eca7fba0480996e2245f5185bf39f2'
+		},
+		size: {
+			type: types.number,
+			optional: bool.false, nullable: bool.false,
+			description: 'The size of this Drive file. (bytes)',
+			example: 51469
+		},
+		url: {
+			type: types.string,
+			optional: bool.false, nullable: bool.true,
+			format: 'url',
+			description: 'The URL of this Drive file.',
+		},
+		folderId: {
+			type: types.string,
+			optional: bool.false, nullable: bool.true,
+			format: 'id',
+			description: 'The parent folder ID of this Drive file.',
+			example: 'xxxxxxxxxx',
+		},
+		isSensitive: {
+			type: types.boolean,
+			optional: bool.false, nullable: bool.false,
+			description: 'Whether this Drive file is sensitive.',
+		},
+	},
+};
diff --git a/src/models/repositories/drive-folder.ts b/src/models/repositories/drive-folder.ts
index ce88adefa4146e6c7191a79f14cd2ffe06277a0e..ef920c432683d809c22f409ae49a2660ad02a0ed 100644
--- a/src/models/repositories/drive-folder.ts
+++ b/src/models/repositories/drive-folder.ts
@@ -1,8 +1,11 @@
 import { EntityRepository, Repository } from 'typeorm';
 import { DriveFolders, DriveFiles } from '..';
-import rap from '@prezzemolo/rap';
 import { DriveFolder } from '../entities/drive-folder';
 import { ensure } from '../../prelude/ensure';
+import { awaitAll } from '../../prelude/await-all';
+import { SchemaType, types, bool } from '../../misc/schema';
+
+export type PackedDriveFolder = SchemaType<typeof packedDriveFolderSchema>;
 
 @EntityRepository(DriveFolder)
 export class DriveFolderRepository extends Repository<DriveFolder> {
@@ -18,16 +21,16 @@ export class DriveFolderRepository extends Repository<DriveFolder> {
 		options?: {
 			detail: boolean
 		}
-	): Promise<Record<string, any>> {
+	): Promise<PackedDriveFolder> {
 		const opts = Object.assign({
 			detail: false
 		}, options);
 
 		const folder = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 
-		return await rap({
+		return await awaitAll({
 			id: folder.id,
-			createdAt: folder.createdAt,
+			createdAt: folder.createdAt.toISOString(),
 			name: folder.name,
 			parentId: folder.parentId,
 
@@ -48,3 +51,50 @@ export class DriveFolderRepository extends Repository<DriveFolder> {
 		});
 	}
 }
+
+export const packedDriveFolderSchema = {
+	type: types.object,
+	optional: bool.false, nullable: bool.false,
+	properties: {
+		id: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'id',
+			description: 'The unique identifier for this Drive folder.',
+			example: 'xxxxxxxxxx',
+		},
+		createdAt: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'date-time',
+			description: 'The date that the Drive folder was created.'
+		},
+		name: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			description: 'The folder name.',
+		},
+		foldersCount: {
+			type: types.number,
+			optional: bool.true, nullable: bool.false,
+			description: 'The count of child folders.',
+		},
+		filesCount: {
+			type: types.number,
+			optional: bool.true, nullable: bool.false,
+			description: 'The count of child files.',
+		},
+		parentId: {
+			type: types.string,
+			optional: bool.false, nullable: bool.true,
+			format: 'id',
+			description: 'The parent folder ID of this folder.',
+			example: 'xxxxxxxxxx',
+		},
+		parent: {
+			type: types.object,
+			optional: bool.true, nullable: bool.true,
+			ref: 'DriveFolder'
+		},
+	},
+};
diff --git a/src/models/repositories/following.ts b/src/models/repositories/following.ts
index 3fff57866f3c720e5d5cffe8d57a7f138f49376e..aba6527face5dd09c5da9e7700c3d935eb4d0cea 100644
--- a/src/models/repositories/following.ts
+++ b/src/models/repositories/following.ts
@@ -1,8 +1,9 @@
 import { EntityRepository, Repository } from 'typeorm';
 import { Users } from '..';
-import rap from '@prezzemolo/rap';
 import { Following } from '../entities/following';
 import { ensure } from '../../prelude/ensure';
+import { awaitAll } from '../../prelude/await-all';
+import { SchemaType, types, bool } from '../../misc/schema';
 
 type LocalFollowerFollowing = Following & {
 	followerHost: null;
@@ -28,6 +29,8 @@ type RemoteFolloweeFollowing = Following & {
 	followeeSharedInbox: string;
 };
 
+export type PackedFollowing = SchemaType<typeof packedFollowingSchema>;
+
 @EntityRepository(Following)
 export class FollowingRepository extends Repository<Following> {
 	public isLocalFollower(following: Following): following is LocalFollowerFollowing {
@@ -64,22 +67,64 @@ export class FollowingRepository extends Repository<Following> {
 			populateFollowee?: boolean;
 			populateFollower?: boolean;
 		}
-	) {
+	): Promise<PackedFollowing> {
 		const following = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 
 		if (opts == null) opts = {};
 
-		return await rap({
+		return await awaitAll({
 			id: following.id,
-			createdAt: following.createdAt,
+			createdAt: following.createdAt.toISOString(),
 			followeeId: following.followeeId,
 			followerId: following.followerId,
 			followee: opts.populateFollowee ? Users.pack(following.followee || following.followeeId, me, {
 				detail: true
-			}) : null,
+			}) : undefined,
 			follower: opts.populateFollower ? Users.pack(following.follower || following.followerId, me, {
 				detail: true
-			}) : null,
+			}) : undefined,
 		});
 	}
 }
+
+export const packedFollowingSchema = {
+	type: types.object,
+	optional: bool.false, nullable: bool.false,
+	properties: {
+		id: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'id',
+			description: 'The unique identifier for this following.',
+			example: 'xxxxxxxxxx',
+		},
+		createdAt: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'date-time',
+			description: 'The date that the following was created.'
+		},
+		followeeId: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'id',
+		},
+		followee: {
+			type: types.object,
+			optional: bool.true, nullable: bool.false,
+			ref: 'User',
+			description: 'The followee.'
+		},
+		followerId: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'id',
+		},
+		follower: {
+			type: types.object,
+			optional: bool.true, nullable: bool.false,
+			ref: 'User',
+			description: 'The follower.'
+		},
+	}
+};
diff --git a/src/models/repositories/games/reversi/matching.ts b/src/models/repositories/games/reversi/matching.ts
index 4d99c6ef76d50e91ea5696aca3924463f3d2de5c..86c9204456593f24d5d7b3a1d24637ec410c3fec 100644
--- a/src/models/repositories/games/reversi/matching.ts
+++ b/src/models/repositories/games/reversi/matching.ts
@@ -1,8 +1,8 @@
 import { EntityRepository, Repository } from 'typeorm';
-import rap from '@prezzemolo/rap';
 import { ReversiMatching } from '../../../entities/games/reversi/matching';
 import { Users } from '../../..';
 import { ensure } from '../../../../prelude/ensure';
+import { awaitAll } from '../../../../prelude/await-all';
 
 @EntityRepository(ReversiMatching)
 export class ReversiMatchingRepository extends Repository<ReversiMatching> {
@@ -12,7 +12,7 @@ export class ReversiMatchingRepository extends Repository<ReversiMatching> {
 	) {
 		const matching = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 
-		return await rap({
+		return await awaitAll({
 			id: matching.id,
 			createdAt: matching.createdAt,
 			parentId: matching.parentId,
diff --git a/src/models/repositories/messaging-message.ts b/src/models/repositories/messaging-message.ts
index 665927353976dabaaf582694b475660961ff2be8..33f95bbd5f1da7929ad043be8eb12e9134072295 100644
--- a/src/models/repositories/messaging-message.ts
+++ b/src/models/repositories/messaging-message.ts
@@ -2,6 +2,9 @@ import { EntityRepository, Repository } from 'typeorm';
 import { MessagingMessage } from '../entities/messaging-message';
 import { Users, DriveFiles } from '..';
 import { ensure } from '../../prelude/ensure';
+import { types, bool, SchemaType } from '../../misc/schema';
+
+export type PackedMessagingMessage = SchemaType<typeof packedMessagingMessageSchema>;
 
 @EntityRepository(MessagingMessage)
 export class MessagingMessageRepository extends Repository<MessagingMessage> {
@@ -15,7 +18,7 @@ export class MessagingMessageRepository extends Repository<MessagingMessage> {
 		options?: {
 			populateRecipient: boolean
 		}
-	) {
+	): Promise<PackedMessagingMessage> {
 		const opts = options || {
 			populateRecipient: true
 		};
@@ -24,15 +27,73 @@ export class MessagingMessageRepository extends Repository<MessagingMessage> {
 
 		return {
 			id: message.id,
-			createdAt: message.createdAt,
+			createdAt: message.createdAt.toISOString(),
 			text: message.text,
 			userId: message.userId,
 			user: await Users.pack(message.user || message.userId, me),
 			recipientId: message.recipientId,
-			recipient: opts.populateRecipient ? await Users.pack(message.recipient || message.recipientId, me) : null,
+			recipient: opts.populateRecipient ? await Users.pack(message.recipient || message.recipientId, me) : undefined,
 			fileId: message.fileId,
 			file: message.fileId ? await DriveFiles.pack(message.fileId) : null,
 			isRead: message.isRead
 		};
 	}
 }
+
+export const packedMessagingMessageSchema = {
+	type: types.object,
+	optional: bool.false, nullable: bool.false,
+	properties: {
+		id: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'id',
+			description: 'The unique identifier for this MessagingMessage.',
+			example: 'xxxxxxxxxx',
+		},
+		createdAt: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'date-time',
+			description: 'The date that the MessagingMessage was created.'
+		},
+		userId: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'id',
+		},
+		user: {
+			type: types.object,
+			ref: 'User',
+			optional: bool.true, nullable: bool.false,
+		},
+		text: {
+			type: types.string,
+			optional: bool.false, nullable: bool.true,
+		},
+		fileId: {
+			type: types.string,
+			optional: bool.true, nullable: bool.true,
+			format: 'id',
+		},
+		file: {
+			type: types.object,
+			optional: bool.true, nullable: bool.true,
+			ref: 'DriveFile',
+		},
+		recipientId: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'id',
+		},
+		recipient: {
+			type: types.object,
+			optional: bool.true, nullable: bool.false,
+			ref: 'User'
+		},
+		isRead: {
+			type: types.boolean,
+			optional: bool.true, nullable: bool.false,
+		},
+	},
+};
diff --git a/src/models/repositories/muting.ts b/src/models/repositories/muting.ts
index 1812e2e71341f570b02b56562c9bb8c175be1515..1e8135a5c91e019ac50a43db716cf9bcc218cdd4 100644
--- a/src/models/repositories/muting.ts
+++ b/src/models/repositories/muting.ts
@@ -1,8 +1,11 @@
 import { EntityRepository, Repository } from 'typeorm';
 import { Users } from '..';
-import rap from '@prezzemolo/rap';
 import { Muting } from '../entities/muting';
 import { ensure } from '../../prelude/ensure';
+import { awaitAll } from '../../prelude/await-all';
+import { types, bool, SchemaType } from '../../misc/schema';
+
+export type PackedMuting = SchemaType<typeof packedMutingSchema>;
 
 @EntityRepository(Muting)
 export class MutingRepository extends Repository<Muting> {
@@ -16,14 +19,47 @@ export class MutingRepository extends Repository<Muting> {
 	public async pack(
 		src: Muting['id'] | Muting,
 		me?: any
-	) {
+	): Promise<PackedMuting> {
 		const muting = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 
-		return await rap({
+		return await awaitAll({
 			id: muting.id,
+			createdAt: muting.createdAt.toISOString(),
+			muteeId: muting.muteeId,
 			mutee: Users.pack(muting.muteeId, me, {
 				detail: true
 			})
 		});
 	}
 }
+
+export const packedMutingSchema = {
+	type: types.object,
+	optional: bool.false, nullable: bool.false,
+	properties: {
+		id: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'id',
+			description: 'The unique identifier for this muting.',
+			example: 'xxxxxxxxxx',
+		},
+		createdAt: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'date-time',
+			description: 'The date that the muting was created.'
+		},
+		muteeId: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'id',
+		},
+		mutee: {
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'User',
+			description: 'The mutee.'
+		},
+	}
+};
diff --git a/src/models/repositories/note-reaction.ts b/src/models/repositories/note-reaction.ts
index 28191d4ab0d1e81278194fbd4d3abe3dcb6e8c4c..85e5b6b0a1f15900a2f848c7fd01f4a780658331 100644
--- a/src/models/repositories/note-reaction.ts
+++ b/src/models/repositories/note-reaction.ts
@@ -2,18 +2,54 @@ import { EntityRepository, Repository } from 'typeorm';
 import { NoteReaction } from '../entities/note-reaction';
 import { Users } from '..';
 import { ensure } from '../../prelude/ensure';
+import { types, bool, SchemaType } from '../../misc/schema';
+
+export type PackedNoteReaction = SchemaType<typeof packedNoteReactionSchema>;
 
 @EntityRepository(NoteReaction)
 export class NoteReactionRepository extends Repository<NoteReaction> {
 	public async pack(
 		src: NoteReaction['id'] | NoteReaction,
 		me?: any
-	) {
+	): Promise<PackedNoteReaction> {
 		const reaction = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 
 		return {
 			id: reaction.id,
+			createdAt: reaction.createdAt.toISOString(),
 			user: await Users.pack(reaction.userId, me),
+			type: reaction.reaction,
 		};
 	}
 }
+
+export const packedNoteReactionSchema = {
+	type: types.object,
+	optional: bool.false, nullable: bool.false,
+	properties: {
+		id: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'id',
+			description: 'The unique identifier for this reaction.',
+			example: 'xxxxxxxxxx',
+		},
+		createdAt: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'date-time',
+			description: 'The date that the reaction was created.'
+		},
+		user: {
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'User',
+			description: 'User who performed this reaction.'
+		},
+		type: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			description: 'The reaction type.'
+		},
+	},
+};
diff --git a/src/models/repositories/note.ts b/src/models/repositories/note.ts
index 1d2ce7a9c91f255a43bc37789e37c86a39e496b9..1dbfabe88d7d007d8783f0f46fecf417e1a3ac08 100644
--- a/src/models/repositories/note.ts
+++ b/src/models/repositories/note.ts
@@ -4,8 +4,11 @@ import { User } from '../entities/user';
 import { unique, concat } from '../../prelude/array';
 import { nyaize } from '../../misc/nyaize';
 import { Emojis, Users, Apps, PollVotes, DriveFiles, NoteReactions, Followings, Polls } from '..';
-import rap from '@prezzemolo/rap';
 import { ensure } from '../../prelude/ensure';
+import { SchemaType, types, bool } from '../../misc/schema';
+import { awaitAll } from '../../prelude/await-all';
+
+export type PackedNote = SchemaType<typeof packedNoteSchema>;
 
 @EntityRepository(Note)
 export class NoteRepository extends Repository<Note> {
@@ -13,18 +16,18 @@ export class NoteRepository extends Repository<Note> {
 		return x.trim().length <= 100;
 	}
 
-	private async hideNote(packedNote: any, meId: User['id'] | null) {
+	private async hideNote(packedNote: PackedNote, meId: User['id'] | null) {
 		let hide = false;
 
 		// visibility が specified かつ自分が指定されていなかったら非表示
-		if (packedNote.visibility == 'specified') {
+		if (packedNote.visibility === 'specified') {
 			if (meId == null) {
 				hide = true;
 			} else if (meId === packedNote.userId) {
 				hide = false;
 			} else {
 				// 指定されているかどうか
-				const specified = packedNote.visibleUserIds.some((id: any) => meId === id);
+				const specified = packedNote.visibleUserIds!.some((id: any) => meId === id);
 
 				if (specified) {
 					hide = false;
@@ -40,10 +43,10 @@ export class NoteRepository extends Repository<Note> {
 				hide = true;
 			} else if (meId === packedNote.userId) {
 				hide = false;
-			} else if (packedNote.reply && (meId === packedNote.reply.userId)) {
+			} else if (packedNote.reply && (meId === (packedNote.reply as PackedNote).userId)) {
 				// 自分の投稿に対するリプライ
 				hide = false;
-			} else if (packedNote.mentions && packedNote.mentions.some((id: any) => meId === id)) {
+			} else if (packedNote.mentions && packedNote.mentions.some(id => meId === id)) {
 				// 自分へのメンション
 				hide = false;
 			} else {
@@ -62,14 +65,13 @@ export class NoteRepository extends Repository<Note> {
 		}
 
 		if (hide) {
-			packedNote.visibleUserIds = null;
+			packedNote.visibleUserIds = undefined;
 			packedNote.fileIds = [];
 			packedNote.files = [];
 			packedNote.text = null;
-			packedNote.poll = null;
+			packedNote.poll = undefined;
 			packedNote.cw = null;
-			packedNote.tags = [];
-			packedNote.geo = null;
+			packedNote.geo = undefined;
 			packedNote.isHidden = true;
 		}
 	}
@@ -92,7 +94,7 @@ export class NoteRepository extends Repository<Note> {
 			detail?: boolean;
 			skipHide?: boolean;
 		}
-	): Promise<Record<string, any>> {
+	): Promise<PackedNote> {
 		const opts = Object.assign({
 			detail: true,
 			skipHide: false
@@ -159,9 +161,9 @@ export class NoteRepository extends Repository<Note> {
 
 		const reactionEmojis = unique(concat([note.emojis, Object.keys(note.reactions)]));
 
-		const packed = await rap({
+		const packed = await awaitAll({
 			id: note.id,
-			createdAt: note.createdAt,
+			createdAt: note.createdAt.toISOString(),
 			app: note.appId ? Apps.pack(note.appId) : undefined,
 			userId: note.userId,
 			user: Users.pack(note.user || note.userId, meId),
@@ -213,3 +215,127 @@ export class NoteRepository extends Repository<Note> {
 		return packed;
 	}
 }
+
+export const packedNoteSchema = {
+	type: types.object,
+	optional: bool.false, nullable: bool.false,
+	properties: {
+		id: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'id',
+			description: 'The unique identifier for this Note.',
+			example: 'xxxxxxxxxx',
+		},
+		createdAt: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'date-time',
+			description: 'The date that the Note was created on Misskey.'
+		},
+		text: {
+			type: types.string,
+			optional: bool.false, nullable: bool.true,
+		},
+		cw: {
+			type: types.string,
+			optional: bool.true, nullable: bool.true,
+		},
+		userId: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'id',
+		},
+		user: {
+			type: types.object,
+			ref: 'User',
+			optional: bool.false, nullable: bool.false,
+		},
+		replyId: {
+			type: types.string,
+			optional: bool.true, nullable: bool.true,
+			format: 'id',
+			example: 'xxxxxxxxxx',
+		},
+		renoteId: {
+			type: types.string,
+			optional: bool.true, nullable: bool.true,
+			format: 'id',
+			example: 'xxxxxxxxxx',
+		},
+		reply: {
+			type: types.object,
+			optional: bool.true, nullable: bool.true,
+			ref: 'Note'
+		},
+		renote: {
+			type: types.object,
+			optional: bool.true, nullable: bool.true,
+			ref: 'Note'
+		},
+		viaMobile: {
+			type: types.boolean,
+			optional: bool.true, nullable: bool.false,
+		},
+		isHidden: {
+			type: types.boolean,
+			optional: bool.true, nullable: bool.false,
+		},
+		visibility: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+		},
+		mentions: {
+			type: types.array,
+			optional: bool.true, nullable: bool.false,
+			items: {
+				type: types.string,
+				optional: bool.false, nullable: bool.false,
+				format: 'id'
+			}
+		},
+		visibleUserIds: {
+			type: types.array,
+			optional: bool.true, nullable: bool.false,
+			items: {
+				type: types.string,
+				optional: bool.false, nullable: bool.false,
+				format: 'id'
+			}
+		},
+		fileIds: {
+			type: types.array,
+			optional: bool.true, nullable: bool.false,
+			items: {
+				type: types.string,
+				optional: bool.false, nullable: bool.false,
+				format: 'id'
+			}
+		},
+		files: {
+			type: types.array,
+			optional: bool.true, nullable: bool.false,
+			items: {
+				type: types.object,
+				optional: bool.false, nullable: bool.false,
+				ref: 'DriveFile'
+			}
+		},
+		tags: {
+			type: types.array,
+			optional: bool.true, nullable: bool.false,
+			items: {
+				type: types.string,
+				optional: bool.false, nullable: bool.false,
+			}
+		},
+		poll: {
+			type: types.object,
+			optional: bool.true, nullable: bool.true,
+		},
+		geo: {
+			type: types.object,
+			optional: bool.true, nullable: bool.true,
+		},
+	},
+};
diff --git a/src/models/repositories/notification.ts b/src/models/repositories/notification.ts
index 4781d4c065068536805b94040dbacc6d3d731ffb..cf77b35a087543361de6fa25c78d6e4a72d04740 100644
--- a/src/models/repositories/notification.ts
+++ b/src/models/repositories/notification.ts
@@ -1,8 +1,11 @@
 import { EntityRepository, Repository } from 'typeorm';
 import { Users, Notes } from '..';
-import rap from '@prezzemolo/rap';
 import { Notification } from '../entities/notification';
 import { ensure } from '../../prelude/ensure';
+import { awaitAll } from '../../prelude/await-all';
+import { types, bool, SchemaType } from '../../misc/schema';
+
+export type PackedNotification = SchemaType<typeof packedNotificationSchema>;
 
 @EntityRepository(Notification)
 export class NotificationRepository extends Repository<Notification> {
@@ -14,12 +17,12 @@ export class NotificationRepository extends Repository<Notification> {
 
 	public async pack(
 		src: Notification['id'] | Notification,
-	) {
+	): Promise<PackedNotification> {
 		const notification = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 
-		return await rap({
+		return await awaitAll({
 			id: notification.id,
-			createdAt: notification.createdAt,
+			createdAt: notification.createdAt.toISOString(),
 			type: notification.type,
 			userId: notification.notifierId,
 			user: Users.pack(notification.notifier || notification.notifierId),
@@ -46,3 +49,39 @@ export class NotificationRepository extends Repository<Notification> {
 		});
 	}
 }
+
+export const packedNotificationSchema = {
+	type: types.object,
+	optional: bool.false, nullable: bool.false,
+	properties: {
+		id: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'id',
+			description: 'The unique identifier for this notification.',
+			example: 'xxxxxxxxxx',
+		},
+		createdAt: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'date-time',
+			description: 'The date that the notification was created.'
+		},
+		type: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			enum: ['follow', 'receiveFollowRequest', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote'],
+			description: 'The type of the notification.'
+		},
+		userId: {
+			type: types.string,
+			optional: bool.true, nullable: bool.true,
+			format: 'id',
+		},
+		user: {
+			type: types.object,
+			ref: 'User',
+			optional: bool.true, nullable: bool.true,
+		},
+	}
+};
diff --git a/src/models/repositories/user-list.ts b/src/models/repositories/user-list.ts
index e591794b8b96756d7485aca030df324790b9cf9b..54231c7f851e803044b675b24c3a29ee5d8cfd17 100644
--- a/src/models/repositories/user-list.ts
+++ b/src/models/repositories/user-list.ts
@@ -2,12 +2,15 @@ import { EntityRepository, Repository } from 'typeorm';
 import { UserList } from '../entities/user-list';
 import { ensure } from '../../prelude/ensure';
 import { UserListJoinings } from '..';
+import { bool, types, SchemaType } from '../../misc/schema';
+
+export type PackedUserList = SchemaType<typeof packedUserListSchema>;
 
 @EntityRepository(UserList)
 export class UserListRepository extends Repository<UserList> {
 	public async pack(
 		src: UserList['id'] | UserList,
-	) {
+	): Promise<PackedUserList> {
 		const userList = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 
 		const users = await UserListJoinings.find({
@@ -16,8 +19,43 @@ export class UserListRepository extends Repository<UserList> {
 
 		return {
 			id: userList.id,
+			createdAt: userList.createdAt.toISOString(),
 			name: userList.name,
 			userIds: users.map(x => x.userId)
 		};
 	}
 }
+
+export const packedUserListSchema = {
+	type: types.object,
+	optional: bool.false, nullable: bool.false,
+	properties: {
+		id: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'id',
+			description: 'The unique identifier for this UserList.',
+			example: 'xxxxxxxxxx',
+		},
+		createdAt: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			format: 'date-time',
+			description: 'The date that the UserList was created.'
+		},
+		name: {
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
+			description: 'The name of the UserList.'
+		},
+		userIds: {
+			type: types.array,
+			nullable: bool.false, optional: bool.true,
+			items: {
+				type: types.string,
+				nullable: bool.false, optional: bool.false,
+				format: 'id',
+			}
+		},
+	},
+};
diff --git a/src/models/repositories/user.ts b/src/models/repositories/user.ts
index afba15eb53e728a994d5f00dfcd6bc82138f2161..6b212203f991d7e16cc9f0cdd9165c858707d512 100644
--- a/src/models/repositories/user.ts
+++ b/src/models/repositories/user.ts
@@ -1,9 +1,12 @@
 import { EntityRepository, Repository, In } from 'typeorm';
 import { User, ILocalUser, IRemoteUser } from '../entities/user';
 import { Emojis, Notes, NoteUnreads, FollowRequests, Notifications, MessagingMessages, UserNotePinings, Followings, Blockings, Mutings, UserProfiles } from '..';
-import rap from '@prezzemolo/rap';
 import { ensure } from '../../prelude/ensure';
 import config from '../../config';
+import { SchemaType, bool, types } from '../../misc/schema';
+import { awaitAll } from '../../prelude/await-all';
+
+export type PackedUser = SchemaType<typeof packedUserSchema>;
 
 @EntityRepository(User)
 export class UserRepository extends Repository<User> {
@@ -71,7 +74,7 @@ export class UserRepository extends Repository<User> {
 			includeSecrets?: boolean,
 			includeHasUnreadNotes?: boolean
 		}
-	): Promise<Record<string, any>> {
+	): Promise<PackedUser> {
 		const opts = Object.assign({
 			detail: false,
 			includeSecrets: false
@@ -86,7 +89,7 @@ export class UserRepository extends Repository<User> {
 
 		const falsy = opts.detail ? false : undefined;
 
-		return await rap({
+		const packed = {
 			id: user.id,
 			name: user.name,
 			username: user.username,
@@ -120,8 +123,8 @@ export class UserRepository extends Repository<User> {
 
 			...(opts.detail ? {
 				url: profile!.url,
-				createdAt: user.createdAt,
-				updatedAt: user.updatedAt,
+				createdAt: user.createdAt.toISOString(),
+				updatedAt: user.updatedAt ? user.updatedAt.toISOString() : null,
 				bannerUrl: user.bannerUrl,
 				bannerColor: user.bannerColor,
 				isLocked: user.isLocked,
@@ -179,7 +182,9 @@ export class UserRepository extends Repository<User> {
 				isBlocked: relation.isBlocked,
 				isMuted: relation.isMuted,
 			} : {})
-		});
+		};
+
+		return await awaitAll(packed);
 	}
 
 	public isLocalUser(user: User): user is ILocalUser {
@@ -216,3 +221,156 @@ export class UserRepository extends Repository<User> {
 	}
 	//#endregion
 }
+
+export const packedUserSchema = {
+	type: types.object,
+	nullable: bool.false, optional: bool.false,
+	properties: {
+		id: {
+			type: types.string,
+			nullable: bool.false, optional: bool.false,
+			format: 'id',
+			description: 'The unique identifier for this User.',
+			example: 'xxxxxxxxxx',
+		},
+		username: {
+			type: types.string,
+			nullable: bool.false, optional: bool.false,
+			description: 'The screen name, handle, or alias that this user identifies themselves with.',
+			example: 'ai'
+		},
+		name: {
+			type: types.string,
+			nullable: bool.true, optional: bool.false,
+			description: 'The name of the user, as they’ve defined it.',
+			example: '藍'
+		},
+		url: {
+			type: types.string,
+			format: 'url',
+			nullable: bool.true, optional: bool.true,
+		},
+		avatarUrl: {
+			type: types.string,
+			format: 'url',
+			nullable: bool.true, optional: bool.false,
+		},
+		avatarColor: {
+			type: types.any,
+			nullable: bool.true, optional: bool.false,
+		},
+		bannerUrl: {
+			type: types.string,
+			format: 'url',
+			nullable: bool.true, optional: bool.true,
+		},
+		bannerColor: {
+			type: types.any,
+			nullable: bool.true, optional: bool.true,
+		},
+		emojis: {
+			type: types.any,
+			nullable: bool.true, optional: bool.false,
+		},
+		host: {
+			type: types.string,
+			nullable: bool.true, optional: bool.false,
+			example: 'misskey.example.com'
+		},
+		description: {
+			type: types.string,
+			nullable: bool.true, optional: bool.true,
+			description: 'The user-defined UTF-8 string describing their account.',
+			example: 'Hi masters, I am Ai!'
+		},
+		birthday: {
+			type: types.string,
+			nullable: bool.true, optional: bool.true,
+			example: '2018-03-12'
+		},
+		createdAt: {
+			type: types.string,
+			nullable: bool.false, optional: bool.true,
+			format: 'date-time',
+			description: 'The date that the user account was created on Misskey.'
+		},
+		updatedAt: {
+			type: types.string,
+			nullable: bool.true, optional: bool.true,
+			format: 'date-time',
+		},
+		location: {
+			type: types.string,
+			nullable: bool.true, optional: bool.true,
+		},
+		followersCount: {
+			type: types.number,
+			nullable: bool.false, optional: bool.true,
+			description: 'The number of followers this account currently has.'
+		},
+		followingCount: {
+			type: types.number,
+			nullable: bool.false, optional: bool.true,
+			description: 'The number of users this account is following.'
+		},
+		notesCount: {
+			type: types.number,
+			nullable: bool.false, optional: bool.true,
+			description: 'The number of Notes (including renotes) issued by the user.'
+		},
+		isBot: {
+			type: types.boolean,
+			nullable: bool.false, optional: bool.true,
+			description: 'Whether this account is a bot.'
+		},
+		pinnedNoteIds: {
+			type: types.array,
+			nullable: bool.false, optional: bool.true,
+			items: {
+				type: types.string,
+				nullable: bool.false, optional: bool.false,
+				format: 'id',
+			}
+		},
+		pinnedNotes: {
+			type: types.array,
+			nullable: bool.false, optional: bool.true,
+			items: {
+				type: types.object,
+				nullable: bool.false, optional: bool.false,
+				ref: 'Note'
+			}
+		},
+		isCat: {
+			type: types.boolean,
+			nullable: bool.false, optional: bool.true,
+			description: 'Whether this account is a cat.'
+		},
+		isAdmin: {
+			type: types.boolean,
+			nullable: bool.false, optional: bool.true,
+			description: 'Whether this account is the admin.'
+		},
+		isModerator: {
+			type: types.boolean,
+			nullable: bool.false, optional: bool.true,
+			description: 'Whether this account is a moderator.'
+		},
+		isVerified: {
+			type: types.boolean,
+			nullable: bool.false, optional: bool.true,
+		},
+		isLocked: {
+			type: types.boolean,
+			nullable: bool.false, optional: bool.true,
+		},
+		hasUnreadSpecifiedNotes: {
+			type: types.boolean,
+			nullable: bool.false, optional: bool.true,
+		},
+		hasUnreadMentions: {
+			type: types.boolean,
+			nullable: bool.false, optional: bool.true,
+		},
+	},
+};
diff --git a/src/prelude/await-all.ts b/src/prelude/await-all.ts
new file mode 100644
index 0000000000000000000000000000000000000000..66303fe3baa55c4e56411fa412615cbf8c21bbd7
--- /dev/null
+++ b/src/prelude/await-all.ts
@@ -0,0 +1,22 @@
+type Await<T> = T extends Promise<infer U> ? U : T;
+
+type AwaitAll<T> = {
+	[P in keyof T]: Await<T[P]>;
+};
+
+export async function awaitAll<T>(obj: T): Promise<AwaitAll<T>> {
+	const target = {} as any;
+	const keys = Object.keys(obj);
+	const rawValues = Object.values(obj);
+	const retValues = ((values: any[]): any[] =>
+		values.map(value => {
+			if (!value || !value.constructor || value.constructor.name !== 'Object') return value;
+			return awaitAll(value);
+		})
+	)(rawValues);
+	const values = await Promise.all(retValues);
+	for (let i = 0; i < values.length; i++) {
+		target[keys[i]] = values[i];
+	}
+	return target;
+}
diff --git a/src/server/api/define.ts b/src/server/api/define.ts
index 990cbf2a86a9a8a01eff63c6672fe2fec67f68f5..1e2600add0f23b5c3b9043b3af2ad64062081b08 100644
--- a/src/server/api/define.ts
+++ b/src/server/api/define.ts
@@ -3,6 +3,7 @@ import { ILocalUser } from '../../models/entities/user';
 import { IEndpointMeta } from './endpoints';
 import { ApiError } from './error';
 import { App } from '../../models/entities/app';
+import { SchemaType } from '../../misc/schema';
 
 type Params<T extends IEndpointMeta> = {
 	[P in keyof T['params']]: NonNullable<T['params']>[P]['transform'] extends Function
@@ -12,7 +13,11 @@ type Params<T extends IEndpointMeta> = {
 
 export type Response = Record<string, any> | void;
 
-export default function <T extends IEndpointMeta>(meta: T, cb: (params: Params<T>, user: ILocalUser, app: App, file?: any, cleanup?: Function) => Promise<Response>): (params: any, user: ILocalUser, app: App, file?: any) => Promise<any> {
+type executor<T extends IEndpointMeta> =
+	(params: Params<T>, user: ILocalUser, app: App, file?: any, cleanup?: Function) => Promise<T['res'] extends undefined ? Response : SchemaType<NonNullable<T['res']>>>;
+
+export default function <T extends IEndpointMeta>(meta: T, cb: executor<T>)
+		: (params: any, user: ILocalUser, app: App, file?: any) => Promise<any> {
 	return (params: any, user: ILocalUser, app: App, file?: any) => {
 		function cleanup() {
 			fs.unlink(file.path, () => {});
diff --git a/src/server/api/endpoints/app/create.ts b/src/server/api/endpoints/app/create.ts
index 9db60d2661ab04c5bf4633fc0be26846c0f5fa0f..833d5060c50293547648ab118c75cb5e57902779 100644
--- a/src/server/api/endpoints/app/create.ts
+++ b/src/server/api/endpoints/app/create.ts
@@ -4,12 +4,13 @@ import define from '../../define';
 import { Apps } from '../../../../models';
 import { genId } from '../../../../misc/gen-id';
 import { unique } from '../../../../prelude/array';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	tags: ['app'],
 
 	requireCredential: false,
-	
+
 	desc: {
 		'ja-JP': 'アプリを作成します。',
 		'en-US': 'Create a application.'
@@ -50,29 +51,12 @@ export const meta = {
 			}
 		},
 	},
-	
+
 	res: {
-		type: 'object',
-		properties: {
-			id: {
-				type: 'string',
-				description: 'アプリケーションのID'
-			},
-			name: {
-				type: 'string',
-				description: 'アプリケーションの名前'
-			},
-			callbackUrl: {
-				type: 'string',
-				nullable: true,
-				description: 'コールバックするURL'
-			},
-			secret: {
-				type: 'string',
-				description: 'アプリケーションのシークレットキー'
-			}
-		}
-	}
+		type: types.object,
+		optional: bool.false, nullable: bool.false,
+		ref: 'App',
+	},
 };
 
 export default define(meta, async (ps, user) => {
diff --git a/src/server/api/endpoints/app/show.ts b/src/server/api/endpoints/app/show.ts
index ce9baed2aebc33a5dda8cc5ab0b5a9fcbb0037fe..e7d3e84388a6c313162ae6d8c086a85411291959 100644
--- a/src/server/api/endpoints/app/show.ts
+++ b/src/server/api/endpoints/app/show.ts
@@ -3,6 +3,7 @@ import { ID } from '../../../../misc/cafy-id';
 import define from '../../define';
 import { ApiError } from '../../error';
 import { Apps } from '../../../../models';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	tags: ['app'],
@@ -13,6 +14,12 @@ export const meta = {
 		},
 	},
 
+	res: {
+		type: types.object,
+		optional: bool.false, nullable: bool.false,
+		ref: 'App',
+	},
+
 	errors: {
 		noSuchApp: {
 			message: 'No such app.',
diff --git a/src/server/api/endpoints/auth/session/generate.ts b/src/server/api/endpoints/auth/session/generate.ts
index bca8d33483686927a3f29664a0c2f19686abe569..9bf27c8e77c6c1a77045cfde000c4411ce18b193 100644
--- a/src/server/api/endpoints/auth/session/generate.ts
+++ b/src/server/api/endpoints/auth/session/generate.ts
@@ -5,12 +5,13 @@ import define from '../../../define';
 import { ApiError } from '../../../error';
 import { Apps, AuthSessions } from '../../../../../models';
 import { genId } from '../../../../../misc/gen-id';
+import { types, bool } from '../../../../../misc/schema';
 
 export const meta = {
 	tags: ['auth'],
 
 	requireCredential: false,
-	
+
 	desc: {
 		'ja-JP': 'アプリを認証するためのトークンを作成します。',
 		'en-US': 'Generate a token for authorize application.'
@@ -27,14 +28,18 @@ export const meta = {
 	},
 
 	res: {
-		type: 'object',
+		type: types.object,
+		optional: bool.false, nullable: bool.false,
 		properties: {
 			token: {
-				type: 'string',
+				type: types.string,
+				optional: bool.false, nullable: bool.false,
 				description: 'セッションのトークン'
 			},
 			url: {
-				type: 'string',
+				type: types.string,
+				optional: bool.false, nullable: bool.false,
+				format: 'url',
 				description: 'セッションのURL'
 			},
 		}
diff --git a/src/server/api/endpoints/auth/session/userkey.ts b/src/server/api/endpoints/auth/session/userkey.ts
index 7126ac52c112c928b497b5afab3a7a0a1a0b5e9b..b7a58c475039c1241c42694fae99b24cf67368a2 100644
--- a/src/server/api/endpoints/auth/session/userkey.ts
+++ b/src/server/api/endpoints/auth/session/userkey.ts
@@ -3,6 +3,7 @@ import define from '../../../define';
 import { ApiError } from '../../../error';
 import { Apps, AuthSessions, AccessTokens, Users } from '../../../../../models';
 import { ensure } from '../../../../../prelude/ensure';
+import { types, bool } from '../../../../../misc/schema';
 
 export const meta = {
 	tags: ['auth'],
@@ -28,15 +29,19 @@ export const meta = {
 	},
 
 	res: {
-		type: 'object',
+		type: types.object,
+		optional: bool.false, nullable: bool.false,
 		properties: {
 			accessToken: {
-				type: 'string',
+				type: types.string,
+				optional: bool.false, nullable: bool.false,
 				description: 'ユーザーのアクセストークン',
 			},
 
 			user: {
-				type: 'User',
+				type: types.object,
+				optional: bool.false, nullable: bool.false,
+				ref: 'User',
 				description: '認証したユーザー'
 			},
 		}
diff --git a/src/server/api/endpoints/blocking/list.ts b/src/server/api/endpoints/blocking/list.ts
index 97f353579ddbb0b7bcd2890b823c1b072092a0e8..5ff1dc0c49ec18f52a09d15e2525ed6e3d8ca9f8 100644
--- a/src/server/api/endpoints/blocking/list.ts
+++ b/src/server/api/endpoints/blocking/list.ts
@@ -3,6 +3,7 @@ import { ID } from '../../../../misc/cafy-id';
 import define from '../../define';
 import { Blockings } from '../../../../models';
 import { makePaginationQuery } from '../../common/make-pagination-query';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -32,9 +33,12 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'Blocking',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'Blocking',
 		}
 	},
 };
diff --git a/src/server/api/endpoints/drive.ts b/src/server/api/endpoints/drive.ts
index adf780301bc89e82a5e6b170f2c162bb4c5b19ae..0c820468b76725dca72fbfe9e21d7ac17e5138a6 100644
--- a/src/server/api/endpoints/drive.ts
+++ b/src/server/api/endpoints/drive.ts
@@ -1,6 +1,7 @@
 import define from '../define';
 import fetchMeta from '../../../misc/fetch-meta';
 import { DriveFiles } from '../../../models';
+import { types, bool } from '../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -15,13 +16,16 @@ export const meta = {
 	kind: 'read:drive',
 
 	res: {
-		type: 'object',
+		type: types.object,
+		optional: bool.false, nullable: bool.false,
 		properties: {
 			capacity: {
-				type: 'number'
+				type: types.number,
+				optional: bool.false, nullable: bool.false,
 			},
 			usage: {
-				type: 'number'
+				type: types.number,
+				optional: bool.false, nullable: bool.false,
 			}
 		}
 	}
diff --git a/src/server/api/endpoints/drive/files.ts b/src/server/api/endpoints/drive/files.ts
index 4e4db6c780bc0c7601bd35d7508c41c61f0a1b97..493e14464caf1f8dac358fae46d8980803cd2105 100644
--- a/src/server/api/endpoints/drive/files.ts
+++ b/src/server/api/endpoints/drive/files.ts
@@ -3,6 +3,7 @@ import { ID } from '../../../../misc/cafy-id';
 import define from '../../define';
 import { DriveFiles } from '../../../../models';
 import { makePaginationQuery } from '../../common/make-pagination-query';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -41,10 +42,13 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'DriveFile',
-		},
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'DriveFile',
+		}
 	},
 };
 
diff --git a/src/server/api/endpoints/drive/files/attached-notes.ts b/src/server/api/endpoints/drive/files/attached-notes.ts
index 7214463dde1bbd85682d3b3b2bb04c30e5fb4053..6bfc95ce8451af6c5e5a6cfd487898b48ba808e7 100644
--- a/src/server/api/endpoints/drive/files/attached-notes.ts
+++ b/src/server/api/endpoints/drive/files/attached-notes.ts
@@ -3,6 +3,7 @@ import { ID } from '../../../../../misc/cafy-id';
 import define from '../../../define';
 import { ApiError } from '../../../error';
 import { DriveFiles } from '../../../../../models';
+import { types, bool } from '../../../../../misc/schema';
 
 export const meta = {
 	stability: 'stable',
@@ -29,10 +30,13 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'Note',
-		},
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'Note',
+		}
 	},
 
 	errors: {
diff --git a/src/server/api/endpoints/drive/files/check-existence.ts b/src/server/api/endpoints/drive/files/check-existence.ts
index 3a87a9497fa1d723ef71df06801d6480113c06f7..5c5cf295472e4b74ddd4d344ead0dd228203e2dd 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 define from '../../../define';
 import { DriveFiles } from '../../../../../models';
+import { types, bool } from '../../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -24,7 +25,13 @@ export const meta = {
 	},
 
 	res: {
-		type: 'DriveFile',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
+		items: {
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'DriveFile',
+		}
 	},
 };
 
diff --git a/src/server/api/endpoints/drive/files/create.ts b/src/server/api/endpoints/drive/files/create.ts
index 340a39a41cabc082fa65ba467c6a468f9d4cf4f7..0f81a1da9922dc6c4384bd73cc1f06e4d654f5e2 100644
--- a/src/server/api/endpoints/drive/files/create.ts
+++ b/src/server/api/endpoints/drive/files/create.ts
@@ -6,6 +6,7 @@ import define from '../../../define';
 import { apiLogger } from '../../../logger';
 import { ApiError } from '../../../error';
 import { DriveFiles } from '../../../../../models';
+import { types, bool } from '../../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -56,7 +57,9 @@ export const meta = {
 	},
 
 	res: {
-		type: 'DriveFile',
+		type: types.object,
+		optional: bool.false, nullable: bool.false,
+		ref: 'DriveFile',
 	},
 
 	errors: {
@@ -87,7 +90,7 @@ export default define(meta, async (ps, user, app, file, cleanup) => {
 	try {
 		// Create file
 		const driveFile = await create(user, file.path, name, null, ps.folderId, ps.force, false, null, null, ps.isSensitive);
-		return DriveFiles.pack(driveFile, { self: true });
+		return await DriveFiles.pack(driveFile, { self: true });
 	} catch (e) {
 		apiLogger.error(e);
 		throw new ApiError();
diff --git a/src/server/api/endpoints/drive/files/find.ts b/src/server/api/endpoints/drive/files/find.ts
index 265850f84c82f912552c200ee7654d8c80dffd08..82b9a97b6d555a6c0a1725552225c1050fafc372 100644
--- a/src/server/api/endpoints/drive/files/find.ts
+++ b/src/server/api/endpoints/drive/files/find.ts
@@ -2,6 +2,7 @@ import $ from 'cafy';
 import { ID } from '../../../../../misc/cafy-id';
 import define from '../../../define';
 import { DriveFiles } from '../../../../../models';
+import { types, bool } from '../../../../../misc/schema';
 
 export const meta = {
 	requireCredential: true,
@@ -22,7 +23,17 @@ export const meta = {
 				'ja-JP': 'フォルダID'
 			}
 		},
-	}
+	},
+
+	res: {
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
+		items: {
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'DriveFile',
+		}
+	},
 };
 
 export default define(meta, async (ps, user) => {
diff --git a/src/server/api/endpoints/drive/files/show.ts b/src/server/api/endpoints/drive/files/show.ts
index e8c0e683c9daf61e98dfd4572bcba6a6ccbc666c..8e74361f9ce1084659e1a67f4194c5aa649b0372 100644
--- a/src/server/api/endpoints/drive/files/show.ts
+++ b/src/server/api/endpoints/drive/files/show.ts
@@ -4,6 +4,7 @@ import define from '../../../define';
 import { ApiError } from '../../../error';
 import { DriveFile } from '../../../../../models/entities/drive-file';
 import { DriveFiles } from '../../../../../models';
+import { types, bool } from '../../../../../misc/schema';
 
 export const meta = {
 	stability: 'stable',
@@ -38,7 +39,9 @@ export const meta = {
 	},
 
 	res: {
-		type: 'DriveFile',
+		type: types.object,
+		optional: bool.false, nullable: bool.false,
+		ref: 'DriveFile',
 	},
 
 	errors: {
diff --git a/src/server/api/endpoints/drive/folders.ts b/src/server/api/endpoints/drive/folders.ts
index 08ae2ff709db826cb0959f4ed43f3e097ba68329..dc3174cd2a09b21a49db77c4f2240b611e99a2d1 100644
--- a/src/server/api/endpoints/drive/folders.ts
+++ b/src/server/api/endpoints/drive/folders.ts
@@ -3,6 +3,7 @@ import { ID } from '../../../../misc/cafy-id';
 import define from '../../define';
 import { DriveFolders } from '../../../../models';
 import { makePaginationQuery } from '../../common/make-pagination-query';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -37,10 +38,13 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'DriveFolder',
-		},
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'DriveFolder',
+		}
 	},
 };
 
diff --git a/src/server/api/endpoints/drive/folders/find.ts b/src/server/api/endpoints/drive/folders/find.ts
index f0989ec5ae474574233b79f61d643bc6292ad2e3..0368d026c3b5b5c813246c8c1412ac05c6348b48 100644
--- a/src/server/api/endpoints/drive/folders/find.ts
+++ b/src/server/api/endpoints/drive/folders/find.ts
@@ -2,6 +2,7 @@ import $ from 'cafy';
 import { ID } from '../../../../../misc/cafy-id';
 import define from '../../../define';
 import { DriveFolders } from '../../../../../models';
+import { types, bool } from '../../../../../misc/schema';
 
 export const meta = {
 	tags: ['drive'],
@@ -25,10 +26,13 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'DriveFolder',
-		},
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'DriveFolder',
+		}
 	},
 };
 
diff --git a/src/server/api/endpoints/drive/folders/show.ts b/src/server/api/endpoints/drive/folders/show.ts
index 60507e7d7f15aacb9e7806dbae9d11ed2595f70d..a020b46aa93c13990d42f0f2988a8d85f9b31989 100644
--- a/src/server/api/endpoints/drive/folders/show.ts
+++ b/src/server/api/endpoints/drive/folders/show.ts
@@ -3,6 +3,7 @@ import { ID } from '../../../../../misc/cafy-id';
 import define from '../../../define';
 import { ApiError } from '../../../error';
 import { DriveFolders } from '../../../../../models';
+import { types, bool } from '../../../../../misc/schema';
 
 export const meta = {
 	stability: 'stable',
@@ -29,7 +30,9 @@ export const meta = {
 	},
 
 	res: {
-		type: 'DriveFolder',
+		type: types.object,
+		optional: bool.false, nullable: bool.false,
+		ref: 'DriveFolder',
 	},
 
 	errors: {
diff --git a/src/server/api/endpoints/drive/stream.ts b/src/server/api/endpoints/drive/stream.ts
index 96d9f82421b9e25c5a5002a73a65cf0da58a9c82..db17979a4ba5400819684322d1434eda1ec33fc6 100644
--- a/src/server/api/endpoints/drive/stream.ts
+++ b/src/server/api/endpoints/drive/stream.ts
@@ -3,6 +3,7 @@ import { ID } from '../../../../misc/cafy-id';
 import define from '../../define';
 import { DriveFiles } from '../../../../models';
 import { makePaginationQuery } from '../../common/make-pagination-query';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	tags: ['drive'],
@@ -31,10 +32,13 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'DriveFile',
-		},
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'DriveFile',
+		}
 	},
 };
 
diff --git a/src/server/api/endpoints/hashtags/list.ts b/src/server/api/endpoints/hashtags/list.ts
index 2998bc1a1389810436d735a7d681c3ef83c2ccb6..89cc92642276d1514297104bf342903d91859558 100644
--- a/src/server/api/endpoints/hashtags/list.ts
+++ b/src/server/api/endpoints/hashtags/list.ts
@@ -1,6 +1,7 @@
 import $ from 'cafy';
 import define from '../../define';
 import { Hashtags } from '../../../../models';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	tags: ['hashtags'],
@@ -47,9 +48,12 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'Hashtag'
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'Hashtag',
 		}
 	},
 };
diff --git a/src/server/api/endpoints/hashtags/search.ts b/src/server/api/endpoints/hashtags/search.ts
index 802f1779933c4f8d392df1ba45cf3fc2b306e6cc..0d2704d01c04568f35a9fc3a79c785aef1339400 100644
--- a/src/server/api/endpoints/hashtags/search.ts
+++ b/src/server/api/endpoints/hashtags/search.ts
@@ -1,6 +1,7 @@
 import $ from 'cafy';
 import define from '../../define';
 import { Hashtags } from '../../../../models';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -37,9 +38,11 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'string'
+			type: types.string,
+			optional: bool.false, nullable: bool.false,
 		}
 	},
 };
diff --git a/src/server/api/endpoints/hashtags/users.ts b/src/server/api/endpoints/hashtags/users.ts
index fa58f2f2c099c0a9a1b80f304ce441259b7dd187..b842f9de64386a7b268a38359345f7956ab933d0 100644
--- a/src/server/api/endpoints/hashtags/users.ts
+++ b/src/server/api/endpoints/hashtags/users.ts
@@ -1,6 +1,7 @@
 import $ from 'cafy';
 import define from '../../define';
 import { Users } from '../../../../models';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	requireCredential: false,
@@ -47,9 +48,12 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'User'
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'User',
 		}
 	},
 };
diff --git a/src/server/api/endpoints/i.ts b/src/server/api/endpoints/i.ts
index afad38c4694e3d0560ae8a764961002dac026d4a..4ecd507e165f1c74548810e3fc69beb18e5734f9 100644
--- a/src/server/api/endpoints/i.ts
+++ b/src/server/api/endpoints/i.ts
@@ -1,5 +1,6 @@
 import define from '../define';
 import { Users } from '../../../models';
+import { types, bool } from '../../../misc/schema';
 
 export const meta = {
 	stability: 'stable',
@@ -15,8 +16,10 @@ export const meta = {
 	params: {},
 
 	res: {
-		type: 'User',
-	}
+		type: types.object,
+		optional: bool.false, nullable: bool.false,
+		ref: 'User',
+	},
 };
 
 export default define(meta, async (ps, user, app) => {
diff --git a/src/server/api/endpoints/i/notifications.ts b/src/server/api/endpoints/i/notifications.ts
index 56074c9d00cfc0be8e8ba71a4eeb97ef9b24391f..41513e5daa0f98d4f9d4651cebdda0129958aa24 100644
--- a/src/server/api/endpoints/i/notifications.ts
+++ b/src/server/api/endpoints/i/notifications.ts
@@ -4,6 +4,7 @@ import { readNotification } from '../../common/read-notification';
 import define from '../../define';
 import { makePaginationQuery } from '../../common/make-pagination-query';
 import { Notifications, Followings, Mutings } from '../../../../models';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -53,10 +54,13 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'Notification',
-		},
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'Notification',
+		}
 	},
 };
 
diff --git a/src/server/api/endpoints/messaging/history.ts b/src/server/api/endpoints/messaging/history.ts
index c2d746e481309241e8917763d8fc5da339a2e998..27e38bbdec62a5778efcd0164e3d820c36b5fe6a 100644
--- a/src/server/api/endpoints/messaging/history.ts
+++ b/src/server/api/endpoints/messaging/history.ts
@@ -3,6 +3,7 @@ import define from '../../define';
 import { MessagingMessage } from '../../../../models/entities/messaging-message';
 import { MessagingMessages, Mutings } from '../../../../models';
 import { Brackets } from 'typeorm';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -24,10 +25,13 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'MessagingMessage',
-		},
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'MessagingMessage',
+		}
 	},
 };
 
diff --git a/src/server/api/endpoints/messaging/messages.ts b/src/server/api/endpoints/messaging/messages.ts
index add21e5f1911ca8ad82571bc58407961bcd75f63..0d5295bff338de695d464e40911a89621a3bf0e2 100644
--- a/src/server/api/endpoints/messaging/messages.ts
+++ b/src/server/api/endpoints/messaging/messages.ts
@@ -6,6 +6,7 @@ import { ApiError } from '../../error';
 import { getUser } from '../../common/getters';
 import { MessagingMessages } from '../../../../models';
 import { makePaginationQuery } from '../../common/make-pagination-query';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -48,10 +49,13 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'MessagingMessage',
-		},
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'MessagingMessage',
+		}
 	},
 
 	errors: {
diff --git a/src/server/api/endpoints/messaging/messages/create.ts b/src/server/api/endpoints/messaging/messages/create.ts
index 30ac0849a3f9a7f3efb0a7757ebcb79ce49a2d3b..388852b9cd46c4f18e6e72f96f65c8e24ba8a9bd 100644
--- a/src/server/api/endpoints/messaging/messages/create.ts
+++ b/src/server/api/endpoints/messaging/messages/create.ts
@@ -9,6 +9,7 @@ import { getUser } from '../../../common/getters';
 import { MessagingMessages, DriveFiles, Mutings } from '../../../../../models';
 import { MessagingMessage } from '../../../../../models/entities/messaging-message';
 import { genId } from '../../../../../misc/gen-id';
+import { types, bool } from '../../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -41,7 +42,9 @@ export const meta = {
 	},
 
 	res: {
-		type: 'MessagingMessage',
+		type: types.object,
+		optional: bool.false, nullable: bool.false,
+		ref: 'MessagingMessage',
 	},
 
 	errors: {
diff --git a/src/server/api/endpoints/meta.ts b/src/server/api/endpoints/meta.ts
index 785f21f22bac726f68228cf42fd7032da2af1508..71b950f4ce171abd9470eff9123fe3683ab76515 100644
--- a/src/server/api/endpoints/meta.ts
+++ b/src/server/api/endpoints/meta.ts
@@ -5,6 +5,7 @@ import define from '../define';
 import fetchMeta from '../../../misc/fetch-meta';
 import * as pkg from '../../../../package.json';
 import { Emojis } from '../../../models';
+import { types, bool } from '../../../misc/schema';
 
 export const meta = {
 	stability: 'stable',
@@ -26,32 +27,40 @@ export const meta = {
 	},
 
 	res: {
-		type: 'object',
+		type: types.object,
+		optional: bool.false, nullable: bool.false,
 		properties: {
 			version: {
-				type: 'string',
+				type: types.string,
+				optional: bool.false, nullable: bool.false,
 				description: 'The version of Misskey of this instance.',
 				example: pkg.version
 			},
 			name: {
-				type: 'string',
+				type: types.string,
+				optional: bool.false, nullable: bool.false,
 				description: 'The name of this instance.',
 			},
 			description: {
-				type: 'string',
+				type: types.string,
+				optional: bool.false, nullable: bool.false,
 				description: 'The description of this instance.',
 			},
 			announcements: {
-				type: 'array',
+				type: types.array,
+				optional: bool.false, nullable: bool.false,
 				items: {
-					type: 'object',
+					type: types.object,
+					optional: bool.false, nullable: bool.false,
 					properties: {
 						title: {
-							type: 'string',
+							type: types.string,
+							optional: bool.false, nullable: bool.false,
 							description: 'The title of the announcement.',
 						},
 						text: {
-							type: 'string',
+							type: types.string,
+							optional: bool.false, nullable: bool.false,
 							description: 'The text of the announcement. (can be HTML)',
 						},
 					}
@@ -59,19 +68,23 @@ export const meta = {
 				description: 'The announcements of this instance.',
 			},
 			disableRegistration: {
-				type: 'boolean',
+				type: types.boolean,
+				optional: bool.false, nullable: bool.false,
 				description: 'Whether disabled open registration.',
 			},
 			disableLocalTimeline: {
-				type: 'boolean',
+				type: types.boolean,
+				optional: bool.false, nullable: bool.false,
 				description: 'Whether disabled LTL and STL.',
 			},
 			disableGlobalTimeline: {
-				type: 'boolean',
+				type: types.boolean,
+				optional: bool.false, nullable: bool.false,
 				description: 'Whether disabled GTL.',
 			},
 			enableEmojiReaction: {
-				type: 'boolean',
+				type: types.boolean,
+				optional: bool.false, nullable: bool.false,
 				description: 'Whether enabled emoji reaction.',
 			},
 		}
diff --git a/src/server/api/endpoints/mute/list.ts b/src/server/api/endpoints/mute/list.ts
index 0fd8a4860d20fdd0751bbacec74364658f5ce9b1..f9ea380c762719d86fa6e5b73b7d84b90d0eb3b5 100644
--- a/src/server/api/endpoints/mute/list.ts
+++ b/src/server/api/endpoints/mute/list.ts
@@ -3,6 +3,7 @@ import { ID } from '../../../../misc/cafy-id';
 import define from '../../define';
 import { makePaginationQuery } from '../../common/make-pagination-query';
 import { Mutings } from '../../../../models';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -32,9 +33,12 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'Muting',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'Muting',
 		}
 	},
 };
diff --git a/src/server/api/endpoints/notes.ts b/src/server/api/endpoints/notes.ts
index 17ba96935088ea217fa69564a970265ef53504c4..7aa19c9a2b024fbe06a5fc70673110807e3af21d 100644
--- a/src/server/api/endpoints/notes.ts
+++ b/src/server/api/endpoints/notes.ts
@@ -3,6 +3,7 @@ import { ID } from '../../../misc/cafy-id';
 import define from '../define';
 import { makePaginationQuery } from '../common/make-pagination-query';
 import { Notes } from '../../../models';
+import { types, bool } from '../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -62,9 +63,12 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'Note',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'Note',
 		}
 	},
 };
diff --git a/src/server/api/endpoints/notes/children.ts b/src/server/api/endpoints/notes/children.ts
index 2b4ae2a3129c60bb864c5835912dfaa956777384..e8861eafa136c0cd0707615619582bbdbcd75fe5 100644
--- a/src/server/api/endpoints/notes/children.ts
+++ b/src/server/api/endpoints/notes/children.ts
@@ -6,6 +6,7 @@ import { generateVisibilityQuery } from '../../common/generate-visibility-query'
 import { generateMuteQuery } from '../../common/generate-mute-query';
 import { Brackets } from 'typeorm';
 import { Notes } from '../../../../models';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -41,10 +42,13 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'Note',
-		},
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'Note',
+		}
 	},
 };
 
diff --git a/src/server/api/endpoints/notes/conversation.ts b/src/server/api/endpoints/notes/conversation.ts
index 6b26e31c07cf28fcb14fd4ecb41acc6af65fa051..acd3ac75ef1d371dd07848233f3932c0a10ac6e7 100644
--- a/src/server/api/endpoints/notes/conversation.ts
+++ b/src/server/api/endpoints/notes/conversation.ts
@@ -5,6 +5,7 @@ import { ApiError } from '../../error';
 import { getNote } from '../../common/getters';
 import { Note } from '../../../../models/entities/note';
 import { Notes } from '../../../../models';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -37,10 +38,13 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'Note',
-		},
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'Note',
+		}
 	},
 
 	errors: {
diff --git a/src/server/api/endpoints/notes/create.ts b/src/server/api/endpoints/notes/create.ts
index 994dfb4dca3c1cde2891c96f4f37492dda3a459b..9822f56a537eebd85db4d3f6ab8ec8b676647f42 100644
--- a/src/server/api/endpoints/notes/create.ts
+++ b/src/server/api/endpoints/notes/create.ts
@@ -10,6 +10,7 @@ import { User } from '../../../../models/entities/user';
 import { Users, DriveFiles, Notes } from '../../../../models';
 import { DriveFile } from '../../../../models/entities/drive-file';
 import { Note } from '../../../../models/entities/note';
+import { types, bool } from '../../../../misc/schema';
 
 let maxNoteTextLength = 1000;
 
@@ -174,10 +175,13 @@ export const meta = {
 	},
 
 	res: {
-		type: 'object',
+		type: types.object,
+		optional: bool.false, nullable: bool.false,
 		properties: {
 			createdNote: {
-				type: 'Note',
+				type: types.object,
+				optional: bool.false, nullable: bool.false,
+				ref: 'Note',
 				description: '作成した投稿'
 			}
 		}
diff --git a/src/server/api/endpoints/notes/featured.ts b/src/server/api/endpoints/notes/featured.ts
index fa9ae39e3a376ac472e6acb12797998ff9f89874..64750815b0b725a3c591adc1541b84f3acb90d0f 100644
--- a/src/server/api/endpoints/notes/featured.ts
+++ b/src/server/api/endpoints/notes/featured.ts
@@ -2,6 +2,7 @@ import $ from 'cafy';
 import define from '../../define';
 import { generateMuteQuery } from '../../common/generate-mute-query';
 import { Notes } from '../../../../models';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -24,10 +25,13 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'Note',
-		},
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'Note',
+		}
 	},
 };
 
diff --git a/src/server/api/endpoints/notes/global-timeline.ts b/src/server/api/endpoints/notes/global-timeline.ts
index ceffb1cf4ac9efaf52b4373f543fe8fa2c95b6c0..e26b9e7da3b9c952043f87e4c204c507a11b5dce 100644
--- a/src/server/api/endpoints/notes/global-timeline.ts
+++ b/src/server/api/endpoints/notes/global-timeline.ts
@@ -7,6 +7,7 @@ import { makePaginationQuery } from '../../common/make-pagination-query';
 import { Notes } from '../../../../models';
 import { generateMuteQuery } from '../../common/generate-mute-query';
 import { activeUsersChart } from '../../../../services/chart';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -46,10 +47,13 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'Note',
-		},
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'Note',
+		}
 	},
 
 	errors: {
diff --git a/src/server/api/endpoints/notes/hybrid-timeline.ts b/src/server/api/endpoints/notes/hybrid-timeline.ts
index effee2b1349ee6fab11535f2a9ad7f3a8a72e5ae..5c27d0c14d1ea7166f56f8ea70921e21d420b0fe 100644
--- a/src/server/api/endpoints/notes/hybrid-timeline.ts
+++ b/src/server/api/endpoints/notes/hybrid-timeline.ts
@@ -9,6 +9,7 @@ import { Brackets } from 'typeorm';
 import { generateVisibilityQuery } from '../../common/generate-visibility-query';
 import { generateMuteQuery } from '../../common/generate-mute-query';
 import { activeUsersChart } from '../../../../services/chart';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -89,10 +90,13 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'Note',
-		},
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'Note',
+		}
 	},
 
 	errors: {
diff --git a/src/server/api/endpoints/notes/local-timeline.ts b/src/server/api/endpoints/notes/local-timeline.ts
index c10c0d7482c58a8a0aabc44c586f0dc0e6d555c5..ed2a5220e1c79e626235a739aa84b2b45d15d991 100644
--- a/src/server/api/endpoints/notes/local-timeline.ts
+++ b/src/server/api/endpoints/notes/local-timeline.ts
@@ -9,6 +9,7 @@ import { makePaginationQuery } from '../../common/make-pagination-query';
 import { generateVisibilityQuery } from '../../common/generate-visibility-query';
 import { activeUsersChart } from '../../../../services/chart';
 import { Brackets } from 'typeorm';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -63,10 +64,13 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'Note',
-		},
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'Note',
+		}
 	},
 
 	errors: {
diff --git a/src/server/api/endpoints/notes/mentions.ts b/src/server/api/endpoints/notes/mentions.ts
index b7f614915b855713373e27c7d534bc7d01e89b3d..02e44492ba3e4cb4d54337828c761cd4fb3e785f 100644
--- a/src/server/api/endpoints/notes/mentions.ts
+++ b/src/server/api/endpoints/notes/mentions.ts
@@ -7,6 +7,7 @@ import { generateVisibilityQuery } from '../../common/generate-visibility-query'
 import { generateMuteQuery } from '../../common/generate-mute-query';
 import { makePaginationQuery } from '../../common/make-pagination-query';
 import { Brackets } from 'typeorm';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -43,10 +44,13 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'Note',
-		},
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'Note',
+		}
 	},
 };
 
diff --git a/src/server/api/endpoints/notes/reactions.ts b/src/server/api/endpoints/notes/reactions.ts
index bcb0b6d1ec79776937b2b7d1859a1a97bd5b5fd1..0773b4faa27abb034d4941e1cda8801082843976 100644
--- a/src/server/api/endpoints/notes/reactions.ts
+++ b/src/server/api/endpoints/notes/reactions.ts
@@ -4,6 +4,7 @@ import define from '../../define';
 import { getNote } from '../../common/getters';
 import { ApiError } from '../../error';
 import { NoteReactions } from '../../../../models';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -44,9 +45,12 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'Reaction'
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'NoteReaction',
 		}
 	},
 
diff --git a/src/server/api/endpoints/notes/renotes.ts b/src/server/api/endpoints/notes/renotes.ts
index 74a8ea918e8bcc6c86edfc89c633d100268ab620..00dfac377095e542ed31e4af5d07021dfbb46e90 100644
--- a/src/server/api/endpoints/notes/renotes.ts
+++ b/src/server/api/endpoints/notes/renotes.ts
@@ -7,6 +7,7 @@ import { generateVisibilityQuery } from '../../common/generate-visibility-query'
 import { generateMuteQuery } from '../../common/generate-mute-query';
 import { makePaginationQuery } from '../../common/make-pagination-query';
 import { Notes } from '../../../../models';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -42,10 +43,13 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'Note',
-		},
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'Note',
+		}
 	},
 
 	errors: {
diff --git a/src/server/api/endpoints/notes/replies.ts b/src/server/api/endpoints/notes/replies.ts
index 980ff2446ecb882b2bcaee439667a932a139dd03..5fb0fd989fd0bd48ab27e0a19c5085d0f194254d 100644
--- a/src/server/api/endpoints/notes/replies.ts
+++ b/src/server/api/endpoints/notes/replies.ts
@@ -5,6 +5,7 @@ import { Notes } from '../../../../models';
 import { makePaginationQuery } from '../../common/make-pagination-query';
 import { generateVisibilityQuery } from '../../common/generate-visibility-query';
 import { generateMuteQuery } from '../../common/generate-mute-query';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -46,10 +47,13 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'Note',
-		},
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'Note',
+		}
 	},
 };
 
diff --git a/src/server/api/endpoints/notes/search-by-tag.ts b/src/server/api/endpoints/notes/search-by-tag.ts
index cba3724b6fc14aa8a10a777bf2c011a12ea85d88..f89539a9b78db281b3bedc63e03b0fb946ce7c7f 100644
--- a/src/server/api/endpoints/notes/search-by-tag.ts
+++ b/src/server/api/endpoints/notes/search-by-tag.ts
@@ -6,6 +6,7 @@ import { Notes } from '../../../../models';
 import { generateMuteQuery } from '../../common/generate-mute-query';
 import { generateVisibilityQuery } from '../../common/generate-visibility-query';
 import { Brackets } from 'typeorm';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -81,10 +82,13 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'Note',
-		},
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'Note',
+		}
 	},
 };
 
diff --git a/src/server/api/endpoints/notes/search.ts b/src/server/api/endpoints/notes/search.ts
index 4d5ac6fbe03f5db5a4646faf4751cfa885b8a384..daf992b6397d6875858517126983add25431403a 100644
--- a/src/server/api/endpoints/notes/search.ts
+++ b/src/server/api/endpoints/notes/search.ts
@@ -4,6 +4,7 @@ import define from '../../define';
 import { ApiError } from '../../error';
 import { Notes } from '../../../../models';
 import { In } from 'typeorm';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -32,10 +33,13 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'Note',
-		},
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'Note',
+		}
 	},
 
 	errors: {
diff --git a/src/server/api/endpoints/notes/show.ts b/src/server/api/endpoints/notes/show.ts
index d41dc20c5498fe3e0194bf72f311f948bf05a685..54b420813d3fd6c8a7eab1050a346c8b9a53bf9d 100644
--- a/src/server/api/endpoints/notes/show.ts
+++ b/src/server/api/endpoints/notes/show.ts
@@ -4,6 +4,7 @@ import define from '../../define';
 import { getNote } from '../../common/getters';
 import { ApiError } from '../../error';
 import { Notes } from '../../../../models';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	stability: 'stable',
@@ -28,7 +29,9 @@ export const meta = {
 	},
 
 	res: {
-		type: 'Note',
+		type: types.object,
+		optional: bool.false, nullable: bool.false,
+		ref: 'Note',
 	},
 
 	errors: {
diff --git a/src/server/api/endpoints/notes/timeline.ts b/src/server/api/endpoints/notes/timeline.ts
index c27f3df1b7ee4c27da7bf5ed04703394879d4e13..5e692db3893eac9534242864c2b3a2d45436026d 100644
--- a/src/server/api/endpoints/notes/timeline.ts
+++ b/src/server/api/endpoints/notes/timeline.ts
@@ -7,6 +7,7 @@ import { generateVisibilityQuery } from '../../common/generate-visibility-query'
 import { generateMuteQuery } from '../../common/generate-mute-query';
 import { activeUsersChart } from '../../../../services/chart';
 import { Brackets } from 'typeorm';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -88,10 +89,13 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'Note',
-		},
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'Note',
+		}
 	},
 };
 
diff --git a/src/server/api/endpoints/notes/user-list-timeline.ts b/src/server/api/endpoints/notes/user-list-timeline.ts
index 05f171af8b17d6d552d24724dc3d9f93c5d8bee1..c16018d434e2717d20a807fa41013496edc2ea7b 100644
--- a/src/server/api/endpoints/notes/user-list-timeline.ts
+++ b/src/server/api/endpoints/notes/user-list-timeline.ts
@@ -6,6 +6,7 @@ import { UserLists, UserListJoinings, Notes } from '../../../../models';
 import { makePaginationQuery } from '../../common/make-pagination-query';
 import { generateVisibilityQuery } from '../../common/generate-visibility-query';
 import { activeUsersChart } from '../../../../services/chart';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -94,10 +95,13 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'Note',
-		},
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'Note',
+		}
 	},
 
 	errors: {
diff --git a/src/server/api/endpoints/stats.ts b/src/server/api/endpoints/stats.ts
index f3ebaa16ad88cf8874c8cf65ed8727708f3be96e..f85109b4b4c0f5c5efc92ada1e4a17c40c9d3fd1 100644
--- a/src/server/api/endpoints/stats.ts
+++ b/src/server/api/endpoints/stats.ts
@@ -1,6 +1,7 @@
 import define from '../define';
 import { Notes, Users } from '../../../models';
 import { federationChart, driveChart } from '../../../services/chart';
+import { bool, types } from '../../../misc/schema';
 
 export const meta = {
 	requireCredential: false,
@@ -15,26 +16,32 @@ export const meta = {
 	},
 
 	res: {
-		type: 'object',
+		type: types.object,
+		optional: bool.false, nullable: bool.false,
 		properties: {
 			notesCount: {
-				type: 'number',
+				type: types.number,
+				optional: bool.false, nullable: bool.false,
 				description: 'The count of all (local/remote) notes of this instance.',
 			},
 			originalNotesCount: {
-				type: 'number',
+				type: types.number,
+				optional: bool.false, nullable: bool.false,
 				description: 'The count of all local notes of this instance.',
 			},
 			usersCount: {
-				type: 'number',
+				type: types.number,
+				optional: bool.false, nullable: bool.false,
 				description: 'The count of all (local/remote) accounts of this instance.',
 			},
 			originalUsersCount: {
-				type: 'number',
+				type: types.number,
+				optional: bool.false, nullable: bool.false,
 				description: 'The count of all local accounts of this instance.',
 			},
 			instances: {
-				type: 'number',
+				type: types.number,
+				optional: bool.false, nullable: bool.false,
 				description: 'The count of federated instances.',
 			},
 		}
@@ -42,7 +49,14 @@ export const meta = {
 };
 
 export default define(meta, async () => {
-	const [notesCount, originalNotesCount, usersCount, originalUsersCount, instances, driveUsageLocal, driveUsageRemote] = await Promise.all([
+	const [notesCount,
+		originalNotesCount,
+		usersCount,
+		originalUsersCount,
+		instances,
+		driveUsageLocal,
+		driveUsageRemote
+	] = await Promise.all([
 		Notes.count(),
 		Notes.count({ userHost: null }),
 		Users.count(),
@@ -53,6 +67,12 @@ export default define(meta, async () => {
 	]);
 
 	return {
-		notesCount, originalNotesCount, usersCount, originalUsersCount, instances, driveUsageLocal, driveUsageRemote
+		notesCount,
+		originalNotesCount,
+		usersCount,
+		originalUsersCount,
+		instances,
+		driveUsageLocal,
+		driveUsageRemote
 	};
 });
diff --git a/src/server/api/endpoints/users.ts b/src/server/api/endpoints/users.ts
index 18af0a26859c00bfc1d7e6a47156d6689d5e8398..c710706f0c89274c126b2104680c5a22caf3fb1e 100644
--- a/src/server/api/endpoints/users.ts
+++ b/src/server/api/endpoints/users.ts
@@ -2,6 +2,7 @@ import $ from 'cafy';
 import define from '../define';
 import { Users } from '../../../models';
 import { generateMuteQueryForUsers } from '../common/generate-mute-query';
+import { types, bool } from '../../../misc/schema';
 
 export const meta = {
 	tags: ['users'],
@@ -53,9 +54,12 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'User',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'User',
 		}
 	},
 };
diff --git a/src/server/api/endpoints/users/followers.ts b/src/server/api/endpoints/users/followers.ts
index 0cb68353ca349c915d8e05e666d3873adae2b315..465b71e2e6e369517bf235bfe3ac2921a3983fcd 100644
--- a/src/server/api/endpoints/users/followers.ts
+++ b/src/server/api/endpoints/users/followers.ts
@@ -5,6 +5,7 @@ import { ApiError } from '../../error';
 import { Users, Followings } from '../../../../models';
 import { makePaginationQuery } from '../../common/make-pagination-query';
 import { toPunyNullable } from '../../../../misc/convert-host';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -48,10 +49,13 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'Following',
-		},
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'Following',
+		}
 	},
 
 	errors: {
diff --git a/src/server/api/endpoints/users/following.ts b/src/server/api/endpoints/users/following.ts
index 2e273dc0c2a84fe9ec548559e892c41f3533af35..2a7748ac64b6177ea6cd3d918dcb093dbda79569 100644
--- a/src/server/api/endpoints/users/following.ts
+++ b/src/server/api/endpoints/users/following.ts
@@ -5,6 +5,7 @@ import { ApiError } from '../../error';
 import { Users, Followings } from '../../../../models';
 import { makePaginationQuery } from '../../common/make-pagination-query';
 import { toPunyNullable } from '../../../../misc/convert-host';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -48,10 +49,13 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'Following',
-		},
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'Following',
+		}
 	},
 
 	errors: {
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 a1d140c6c9d6250bb0b60491920eb4d61baa1544..420936c0899881c5cbd09f635b1405d480ba12e1 100644
--- a/src/server/api/endpoints/users/get-frequently-replied-users.ts
+++ b/src/server/api/endpoints/users/get-frequently-replied-users.ts
@@ -6,6 +6,7 @@ import { ApiError } from '../../error';
 import { getUser } from '../../common/getters';
 import { Not, In } from 'typeorm';
 import { Notes, Users } from '../../../../models';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	tags: ['users'],
@@ -28,9 +29,12 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'User',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'User',
 		}
 	},
 
diff --git a/src/server/api/endpoints/users/lists/create.ts b/src/server/api/endpoints/users/lists/create.ts
index 21dc6d331df11fe63a79e12265e5e1571ff899c0..79efffbf9ec31507d57318f7a72c5ebf1d93ad9c 100644
--- a/src/server/api/endpoints/users/lists/create.ts
+++ b/src/server/api/endpoints/users/lists/create.ts
@@ -3,6 +3,7 @@ import define from '../../../define';
 import { UserLists } from '../../../../../models';
 import { genId } from '../../../../../misc/gen-id';
 import { UserList } from '../../../../../models/entities/user-list';
+import { types, bool } from '../../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -17,10 +18,16 @@ export const meta = {
 	kind: 'write:account',
 
 	params: {
-		title: {
+		name: {
 			validator: $.str.range(1, 100)
 		}
-	}
+	},
+
+	res: {
+		type: types.object,
+		optional: bool.false, nullable: bool.false,
+		ref: 'UserList',
+	},
 };
 
 export default define(meta, async (ps, user) => {
@@ -28,7 +35,7 @@ export default define(meta, async (ps, user) => {
 		id: genId(),
 		createdAt: new Date(),
 		userId: user.id,
-		name: ps.title,
+		name: ps.name,
 	} as UserList);
 
 	return await UserLists.pack(userList);
diff --git a/src/server/api/endpoints/users/lists/list.ts b/src/server/api/endpoints/users/lists/list.ts
index b05fc45527f9bcc6fd6183e522c2b0179b2f8830..684086b5c6c7a8e9230652fc0068fc6c68dd74aa 100644
--- a/src/server/api/endpoints/users/lists/list.ts
+++ b/src/server/api/endpoints/users/lists/list.ts
@@ -1,5 +1,6 @@
 import define from '../../../define';
 import { UserLists } from '../../../../../models';
+import { types, bool } from '../../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -13,10 +14,13 @@ export const meta = {
 	kind: 'read:account',
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'UserList',
-		},
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'UserList',
+		}
 	},
 };
 
diff --git a/src/server/api/endpoints/users/lists/show.ts b/src/server/api/endpoints/users/lists/show.ts
index 1a997ec7c5a52d8c9c27ba40c3c0b9319eb260c2..395f9352d42ebc9f0a7f75142f9917d7683ea3b3 100644
--- a/src/server/api/endpoints/users/lists/show.ts
+++ b/src/server/api/endpoints/users/lists/show.ts
@@ -3,6 +3,7 @@ import { ID } from '../../../../../misc/cafy-id';
 import define from '../../../define';
 import { ApiError } from '../../../error';
 import { UserLists } from '../../../../../models';
+import { types, bool } from '../../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -23,7 +24,9 @@ export const meta = {
 	},
 
 	res: {
-		type: 'UserList'
+		type: types.object,
+		optional: bool.false, nullable: bool.false,
+		ref: 'UserList',
 	},
 
 	errors: {
diff --git a/src/server/api/endpoints/users/notes.ts b/src/server/api/endpoints/users/notes.ts
index 4691a9939417baaf3a7e93079136b4f6108cbb4e..fdc50e4dae55b5255fc856b687e23bfd1d8f6fe4 100644
--- a/src/server/api/endpoints/users/notes.ts
+++ b/src/server/api/endpoints/users/notes.ts
@@ -8,6 +8,7 @@ import { generateVisibilityQuery } from '../../common/generate-visibility-query'
 import { Notes } from '../../../../models';
 import { generateMuteQuery } from '../../common/generate-mute-query';
 import { Brackets } from 'typeorm';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -119,10 +120,13 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'Note',
-		},
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'Note',
+		}
 	},
 
 	errors: {
diff --git a/src/server/api/endpoints/users/recommendation.ts b/src/server/api/endpoints/users/recommendation.ts
index 9e16e34e3920f71576cebca3a0f5e0d2a2faff47..67b646a35f7a10e8e58d7edeab3f4d6613eed9f7 100644
--- a/src/server/api/endpoints/users/recommendation.ts
+++ b/src/server/api/endpoints/users/recommendation.ts
@@ -3,6 +3,7 @@ import $ from 'cafy';
 import define from '../../define';
 import { Users, Followings } from '../../../../models';
 import { generateMuteQueryForUsers } from '../../common/generate-mute-query';
+import { types, bool } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -28,9 +29,12 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'User',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'User',
 		}
 	},
 };
diff --git a/src/server/api/endpoints/users/search.ts b/src/server/api/endpoints/users/search.ts
index 96da221d97384a9521a6d2228e2bc5d4c6b9293f..2809465fd78f62f30c2de24818c873116d992522 100644
--- a/src/server/api/endpoints/users/search.ts
+++ b/src/server/api/endpoints/users/search.ts
@@ -2,6 +2,7 @@ import $ from 'cafy';
 import define from '../../define';
 import { Users } from '../../../../models';
 import { User } from '../../../../models/entities/user';
+import { bool, types } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -54,9 +55,12 @@ export const meta = {
 	},
 
 	res: {
-		type: 'array',
+		type: types.array,
+		optional: bool.false, nullable: bool.false,
 		items: {
-			type: 'User',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
+			ref: 'User',
 		}
 	},
 };
diff --git a/src/server/api/endpoints/users/show.ts b/src/server/api/endpoints/users/show.ts
index a401166c5564ca1fd1907dddb503371d93262666..820c44e81ba8179bb3e4532a4868cf5ba471e6c4 100644
--- a/src/server/api/endpoints/users/show.ts
+++ b/src/server/api/endpoints/users/show.ts
@@ -6,6 +6,7 @@ import { ApiError } from '../../error';
 import { ID } from '../../../../misc/cafy-id';
 import { Users } from '../../../../models';
 import { In } from 'typeorm';
+import { bool, types } from '../../../../misc/schema';
 
 export const meta = {
 	desc: {
@@ -42,7 +43,9 @@ export const meta = {
 	},
 
 	res: {
-		type: 'User',
+		type: types.object,
+		optional: bool.false, nullable: bool.false,
+		ref: 'User',
 	},
 
 	errors: {
diff --git a/src/server/api/openapi/description.ts b/src/server/api/openapi/description.ts
index 0a4c8699d18b94c14f75dbde7b5ad6ea1aed393d..9006dfbfa475dce20d645c56e7f9642e90a865c5 100644
--- a/src/server/api/openapi/description.ts
+++ b/src/server/api/openapi/description.ts
@@ -44,20 +44,20 @@ export function getDescription(lang = 'ja-JP'): string {
 	const descriptions = {
 		'ja-JP': `**Misskey is a decentralized microblogging platform.**
 
-## Usage
+# Usage
 **APIはすべてPOSTでリクエスト/レスポンスともにJSON形式です。**
 一部のAPIはリクエストに認証情報(APIキー)が必要です。リクエストの際に\`i\`というパラメータでAPIキーを添付してください。
 
-### 自分のアカウントのAPIキーを取得する
+## 自分のアカウントのAPIキーを取得する
 「設定 > API」で、自分のAPIキーを取得できます。
 
 > アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。
 
-### アプリケーションとしてAPIキーを取得する
+## アプリケーションとしてAPIキーを取得する
 直接ユーザーのAPIキーをアプリケーションが扱うのはセキュリティ上のリスクがあるので、
 アプリケーションからAPIを利用する際には、アプリケーションとアプリケーションを利用するユーザーが結び付けられた専用のAPIキーを発行します。
 
-#### 1.アプリケーションを登録する
+### 1.アプリケーションを登録する
 まず、あなたのアプリケーションやWebサービス(以後、あなたのアプリと呼びます)をMisskeyに登録します。
 [デベロッパーセンター](/dev)にアクセスし、「アプリ > アプリ作成」からアプリを作成してください。
 
@@ -65,7 +65,7 @@ export function getDescription(lang = 'ja-JP'): string {
 
 > アプリに成りすまされる可能性があるため、極力このシークレットキーは公開しないようにしてください。</p>
 
-#### 2.ユーザーに認証させる
+### 2.ユーザーに認証させる
 アプリを使ってもらうには、ユーザーにアカウントへのアクセスの許可をもらう必要があります。
 
 認証セッションを開始するには、[${config.apiUrl}/auth/session/generate](#operation/auth/session/generate) へパラメータに\`appSecret\`としてシークレットキーを含めたリクエストを送信します。
@@ -76,7 +76,7 @@ export function getDescription(lang = 'ja-JP'): string {
 
 あなたのアプリがコールバックURLを設定していない場合、ユーザーがあなたのアプリの連携を許可したことを(何らかの方法で(たとえばボタンを押させるなど))確認出来るようにしてください。
 
-#### 3.アクセストークンを取得する
+### 3.アクセストークンを取得する
 ユーザーが連携を許可したら、[${config.apiUrl}/auth/session/userkey](#operation/auth/session/userkey) へリクエストを送信します。
 
 上手くいけば、認証したユーザーのアクセストークンがレスポンスとして取得できます。おめでとうございます!
@@ -88,7 +88,7 @@ APIキーの生成方法を擬似コードで表すと次のようになりま
 const i = sha256(userToken + secretKey);
 \`\`\`
 
-## Permissions
+# Permissions
 |Permisson (kind)|Description|Endpoints|
 |:--|:--|:--|
 ${permissionTable}
diff --git a/src/server/api/openapi/gen-spec.ts b/src/server/api/openapi/gen-spec.ts
index d194c6c8a8efd8c7830ade501e6e4e8234eb5cd0..de26b970ea7a9e039f304102c0c07fbc5a8a330c 100644
--- a/src/server/api/openapi/gen-spec.ts
+++ b/src/server/api/openapi/gen-spec.ts
@@ -2,9 +2,8 @@ import endpoints from '../endpoints';
 import { Context } from 'cafy';
 import config from '../../../config';
 import { errors as basicErrors } from './errors';
-import { schemas } from './schemas';
+import { schemas, convertSchemaToOpenApiSchema } from './schemas';
 import { getDescription } from './description';
-import { convertOpenApiSchema } from '../../../misc/schema';
 
 export function genOpenapiSpec(lang = 'ja-JP') {
 	const spec = {
@@ -59,7 +58,7 @@ export function genOpenapiSpec(lang = 'ja-JP') {
 			deprecated: (param.data || {}).deprecated,
 			...((param.data || {}).default ? { default: (param.data || {}).default } : {}),
 			type: param.name === 'ID' ? 'string' : param.name.toLowerCase(),
-			...(param.name === 'ID' ? { example: 'xxxxxxxxxxxxxxxxxxxxxxxx', format: 'id' } : {}),
+			...(param.name === 'ID' ? { example: 'xxxxxxxxxx', format: 'id' } : {}),
 			nullable: param.isNullable,
 			...(param.name === 'String' ? {
 				...((param as any).enum ? { enum: (param as any).enum } : {}),
@@ -106,7 +105,7 @@ export function genOpenapiSpec(lang = 'ja-JP') {
 
 		const required = endpoint.meta.params ? Object.entries(endpoint.meta.params).filter(([k, v]) => !v.validator.isOptional).map(([k, v]) => k) : [];
 
-		const resSchema = endpoint.meta.res ? convertOpenApiSchema(endpoint.meta.res) : {};
+		const resSchema = endpoint.meta.res ? convertSchemaToOpenApiSchema(endpoint.meta.res) : {};
 
 		let desc = (endpoint.meta.desc ? endpoint.meta.desc[lang] : 'No description provided.') + '\n\n';
 		desc += `**Credential required**: *${endpoint.meta.requireCredential ? 'Yes' : 'No'}*`;
diff --git a/src/server/api/openapi/schemas.ts b/src/server/api/openapi/schemas.ts
index 65826d9321729187af3b42b857efbddae388d865..e54f989e7484316a1dc0b9cae4d6f174321f4db9 100644
--- a/src/server/api/openapi/schemas.ts
+++ b/src/server/api/openapi/schemas.ts
@@ -1,3 +1,39 @@
+import { packedUserSchema } from '../../../models/repositories/user';
+import { Schema } from '../../../misc/schema';
+import { packedNoteSchema } from '../../../models/repositories/note';
+import { packedUserListSchema } from '../../../models/repositories/user-list';
+import { packedAppSchema } from '../../../models/repositories/app';
+import { packedMessagingMessageSchema } from '../../../models/repositories/messaging-message';
+import { packedNotificationSchema } from '../../../models/repositories/notification';
+import { packedDriveFileSchema } from '../../../models/repositories/drive-file';
+import { packedDriveFolderSchema } from '../../../models/repositories/drive-folder';
+import { packedFollowingSchema } from '../../../models/repositories/following';
+import { packedMutingSchema } from '../../../models/repositories/muting';
+import { packedBlockingSchema } from '../../../models/repositories/blocking';
+import { packedNoteReactionSchema } from '../../../models/repositories/note-reaction';
+
+export function convertSchemaToOpenApiSchema(schema: Schema) {
+	const res: any = schema;
+
+	if (schema.type === 'object' && schema.properties) {
+		res.required = Object.entries(schema.properties).filter(([k, v]) => v.optional !== true).map(([k]) => k);
+
+		for (const k of Object.keys(schema.properties)) {
+			res.properties[k] = convertSchemaToOpenApiSchema(schema.properties[k]);
+		}
+	}
+
+	if (schema.type === 'array' && schema.items) {
+		res.items = convertSchemaToOpenApiSchema(schema.items);
+	}
+
+	if (schema.ref) {
+		res.$ref = `#/components/schemas/${schema.ref}`;
+	}
+
+	return res;
+}
+
 export const schemas = {
 	Error: {
 		type: 'object',
@@ -26,413 +62,18 @@ export const schemas = {
 		required: ['error']
 	},
 
-	User: {
-		type: 'object',
-		properties: {
-			id: {
-				type: 'string',
-				format: 'id',
-				description: 'The unique identifier for this User.',
-				example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
-			},
-			username: {
-				type: 'string',
-				description: 'The screen name, handle, or alias that this user identifies themselves with.',
-				example: 'ai'
-			},
-			name: {
-				type: 'string',
-				nullable: true,
-				description: 'The name of the user, as they’ve defined it.',
-				example: '藍'
-			},
-			host: {
-				type: 'string',
-				nullable: true,
-				example: 'misskey.example.com'
-			},
-			description: {
-				type: 'string',
-				nullable: true,
-				description: 'The user-defined UTF-8 string describing their account.',
-				example: 'Hi masters, I am Ai!'
-			},
-			createdAt: {
-				type: 'string',
-				format: 'date-time',
-				description: 'The date that the user account was created on Misskey.'
-			},
-			followersCount: {
-				type: 'number',
-				description: 'The number of followers this account currently has.'
-			},
-			followingCount: {
-				type: 'number',
-				description: 'The number of users this account is following.'
-			},
-			notesCount: {
-				type: 'number',
-				description: 'The number of Notes (including renotes) issued by the user.'
-			},
-			isBot: {
-				type: 'boolean',
-				description: 'Whether this account is a bot.'
-			},
-			isCat: {
-				type: 'boolean',
-				description: 'Whether this account is a cat.'
-			},
-			isAdmin: {
-				type: 'boolean',
-				description: 'Whether this account is the admin.'
-			},
-			isVerified: {
-				type: 'boolean'
-			},
-			isLocked: {
-				type: 'boolean'
-			},
-		},
-		required: ['id', 'name', 'username', 'createdAt']
-	},
-
-	UserList: {
-		type: 'object',
-		properties: {
-			id: {
-				type: 'string',
-				format: 'id',
-				description: 'The unique identifier for this UserList.',
-				example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
-			},
-			createdAt: {
-				type: 'string',
-				format: 'date-time',
-				description: 'The date that the UserList was created.'
-			},
-			title: {
-				type: 'string',
-				description: 'The name of the UserList.'
-			},
-		},
-		required: ['id', 'createdAt', 'title']
-	},
-
-	MessagingMessage: {
-		type: 'object',
-		properties: {
-			id: {
-				type: 'string',
-				format: 'id',
-				description: 'The unique identifier for this MessagingMessage.',
-				example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
-			},
-			createdAt: {
-				type: 'string',
-				format: 'date-time',
-				description: 'The date that the MessagingMessage was created.'
-			},
-			text: {
-				type: 'string',
-				nullable: true
-			},
-			file: {
-				type: 'DriveFile',
-				nullable: true
-			},
-			recipientId: {
-				type: 'string',
-				format: 'id',
-			},
-			recipient: {
-				$ref: '#/components/schemas/User'
-			},
-		},
-		required: ['id', 'createdAt']
-	},
-
-	Note: {
-		type: 'object',
-		properties: {
-			id: {
-				type: 'string',
-				format: 'id',
-				description: 'The unique identifier for this Note.',
-				example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
-			},
-			createdAt: {
-				type: 'string',
-				format: 'date-time',
-				description: 'The date that the Note was created on Misskey.'
-			},
-			text: {
-				type: 'string'
-			},
-			cw: {
-				type: 'string'
-			},
-			userId: {
-				type: 'string',
-				format: 'id',
-			},
-			user: {
-				$ref: '#/components/schemas/User'
-			},
-			replyId: {
-				type: 'string',
-				format: 'id',
-				example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
-			},
-			renoteId: {
-				type: 'string',
-				format: 'id',
-				example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
-			},
-			reply: {
-				$ref: '#/components/schemas/Note'
-			},
-			renote: {
-				$ref: '#/components/schemas/Note'
-			},
-			viaMobile: {
-				type: 'boolean'
-			},
-			visibility: {
-				type: 'string'
-			},
-		},
-		required: ['id', 'userId', 'createdAt']
-	},
-
-	Notification: {
-		type: 'object',
-		properties: {
-			id: {
-				type: 'string',
-				format: 'id',
-				description: 'The unique identifier for this notification.',
-				example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
-			},
-			createdAt: {
-				type: 'string',
-				format: 'date-time',
-				description: 'The date that the notification was created.'
-			},
-			type: {
-				type: 'string',
-				enum: ['follow', 'receiveFollowRequest', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote'],
-				description: 'The type of the notification.'
-			},
-		},
-		required: ['id', 'createdAt', 'type']
-	},
-
-	DriveFile: {
-		type: 'object',
-		properties: {
-			id: {
-				type: 'string',
-				format: 'id',
-				description: 'The unique identifier for this Drive file.',
-				example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
-			},
-			createdAt: {
-				type: 'string',
-				format: 'date-time',
-				description: 'The date that the Drive file was created on Misskey.'
-			},
-			name: {
-				type: 'string',
-				description: 'The file name with extension.',
-				example: 'lenna.jpg'
-			},
-			type: {
-				type: 'string',
-				description: 'The MIME type of this Drive file.',
-				example: 'image/jpeg'
-			},
-			md5: {
-				type: 'string',
-				format: 'md5',
-				description: 'The MD5 hash of this Drive file.',
-				example: '15eca7fba0480996e2245f5185bf39f2'
-			},
-			size: {
-				type: 'number',
-				description: 'The size of this Drive file. (bytes)',
-				example: 51469
-			},
-			folderId: {
-				type: 'string',
-				format: 'id',
-				nullable: true,
-				description: 'The parent folder ID of this Drive file.',
-				example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
-			},
-			isSensitive: {
-				type: 'boolean',
-				description: 'Whether this Drive file is sensitive.',
-			},
-		},
-		required: ['id', 'createdAt', 'name', 'type', 'size', 'md5']
-	},
-
-	DriveFolder: {
-		type: 'object',
-		properties: {
-			id: {
-				type: 'string',
-				format: 'id',
-				description: 'The unique identifier for this Drive folder.',
-				example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
-			},
-			createdAt: {
-				type: 'string',
-				format: 'date-time',
-				description: 'The date that the Drive folder was created.'
-			},
-			name: {
-				type: 'string',
-				description: 'The folder name.',
-			},
-			foldersCount: {
-				type: 'number',
-				description: 'The count of child folders.',
-			},
-			filesCount: {
-				type: 'number',
-				description: 'The count of child files.',
-			},
-			parentId: {
-				type: 'string',
-				format: 'id',
-				nullable: true,
-				description: 'The parent folder ID of this folder.',
-				example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
-			},
-			parent: {
-				$ref: '#/components/schemas/DriveFolder'
-			},
-		},
-		required: ['id', 'createdAt', 'name']
-	},
-
-	Following: {
-		type: 'object',
-		properties: {
-			id: {
-				type: 'string',
-				format: 'id',
-				description: 'The unique identifier for this following.',
-				example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
-			},
-			createdAt: {
-				type: 'string',
-				format: 'date-time',
-				description: 'The date that the following was created.'
-			},
-			followeeId: {
-				type: 'string',
-				format: 'id',
-			},
-			followee: {
-				$ref: '#/components/schemas/User',
-				description: 'The followee.'
-			},
-			followerId: {
-				type: 'string',
-				format: 'id',
-			},
-			follower: {
-				$ref: '#/components/schemas/User',
-				description: 'The follower.'
-			},
-		},
-		required: ['id', 'createdAt', 'followeeId', 'followerId']
-	},
-
-	Muting: {
-		type: 'object',
-		properties: {
-			id: {
-				type: 'string',
-				format: 'id',
-				description: 'The unique identifier for this mute.',
-				example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
-			},
-			createdAt: {
-				type: 'string',
-				format: 'date-time',
-				description: 'The date that the mute was created.'
-			},
-			mutee: {
-				$ref: '#/components/schemas/User',
-				description: 'The mutee.'
-			},
-		},
-		required: ['id', 'createdAt', 'mutee']
-	},
-
-	Blocking: {
-		type: 'object',
-		properties: {
-			id: {
-				type: 'string',
-				format: 'id',
-				description: 'The unique identifier for this block.',
-				example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
-			},
-			createdAt: {
-				type: 'string',
-				format: 'date-time',
-				description: 'The date that the block was created.'
-			},
-			blockee: {
-				$ref: '#/components/schemas/User',
-				description: 'The blockee.'
-			},
-		},
-		required: ['id', 'createdAt', 'blockee']
-	},
-
-	Reaction: {
-		type: 'object',
-		properties: {
-			id: {
-				type: 'string',
-				format: 'id',
-				description: 'The unique identifier for this reaction.',
-				example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
-			},
-			createdAt: {
-				type: 'string',
-				format: 'date-time',
-				description: 'The date that the reaction was created.'
-			},
-			user: {
-				$ref: '#/components/schemas/User',
-				description: 'User who performed this reaction.'
-			},
-			type: {
-				type: 'string',
-				enum: [
-					'like',
-					'love',
-					'laugh',
-					'hmm',
-					'surprise',
-					'congrats',
-					'angry',
-					'confused',
-					'rip',
-					'pudding',
-					'star'
-				],
-				description: 'The reaction type.'
-			},
-		},
-		required: ['id', 'createdAt', 'user', 'type']
-	},
+	User: convertSchemaToOpenApiSchema(packedUserSchema),
+	UserList: convertSchemaToOpenApiSchema(packedUserListSchema),
+	App: convertSchemaToOpenApiSchema(packedAppSchema),
+	MessagingMessage: convertSchemaToOpenApiSchema(packedMessagingMessageSchema),
+	Note: convertSchemaToOpenApiSchema(packedNoteSchema),
+	Notification: convertSchemaToOpenApiSchema(packedNotificationSchema),
+	DriveFile: convertSchemaToOpenApiSchema(packedDriveFileSchema),
+	DriveFolder: convertSchemaToOpenApiSchema(packedDriveFolderSchema),
+	Following: convertSchemaToOpenApiSchema(packedFollowingSchema),
+	Muting: convertSchemaToOpenApiSchema(packedMutingSchema),
+	Blocking: convertSchemaToOpenApiSchema(packedBlockingSchema),
+	NoteReaction: convertSchemaToOpenApiSchema(packedNoteReactionSchema),
 
 	Hashtag: {
 		type: 'object',
diff --git a/src/server/api/private/signup.ts b/src/server/api/private/signup.ts
index f8dba2eb292f19f1a074269946919f8df81466be..57158975356a875c6d359c99ae2ee29edee79767 100644
--- a/src/server/api/private/signup.ts
+++ b/src/server/api/private/signup.ts
@@ -135,7 +135,7 @@ export default async (ctx: Koa.BaseContext) => {
 		includeSecrets: true
 	});
 
-	res.token = secret;
+	(res as any).token = secret;
 
 	ctx.body = res;
 };
diff --git a/src/server/api/stream/channels/global-timeline.ts b/src/server/api/stream/channels/global-timeline.ts
index 3aaadc1a4a81e1aa97e64bcd597ba13aaf19e571..7af6719d29ccc70e83f446539030be162dfee3ea 100644
--- a/src/server/api/stream/channels/global-timeline.ts
+++ b/src/server/api/stream/channels/global-timeline.ts
@@ -3,6 +3,7 @@ import shouldMuteThisNote from '../../../../misc/should-mute-this-note';
 import Channel from '../channel';
 import fetchMeta from '../../../../misc/fetch-meta';
 import { Notes } from '../../../../models';
+import { PackedNote } from '../../../../models/repositories/note';
 
 export default class extends Channel {
 	public readonly chName = 'globalTimeline';
@@ -21,7 +22,7 @@ export default class extends Channel {
 	}
 
 	@autobind
-	private async onNote(note: any) {
+	private async onNote(note: PackedNote) {
 		if (note.visibility !== 'public') return;
 
 		// リプライなら再pack
diff --git a/src/server/api/stream/channels/hashtag.ts b/src/server/api/stream/channels/hashtag.ts
index 36c56c7ab6bee77071d270dbd48774a8abb7aecc..e55a5083282e3002c4a280f280594f1b7ec22ca1 100644
--- a/src/server/api/stream/channels/hashtag.ts
+++ b/src/server/api/stream/channels/hashtag.ts
@@ -2,6 +2,7 @@ import autobind from 'autobind-decorator';
 import shouldMuteThisNote from '../../../../misc/should-mute-this-note';
 import Channel from '../channel';
 import { Notes } from '../../../../models';
+import { PackedNote } from '../../../../models/repositories/note';
 
 export default class extends Channel {
 	public readonly chName = 'hashtag';
@@ -20,8 +21,8 @@ export default class extends Channel {
 	}
 
 	@autobind
-	private async onNote(note: any) {
-		const noteTags = note.tags.map((t: string) => t.toLowerCase());
+	private async onNote(note: PackedNote) {
+		const noteTags = note.tags ? note.tags.map((t: string) => t.toLowerCase()) : [];
 		const matched = this.q.some(tags => tags.every(tag => noteTags.includes(tag.toLowerCase())));
 		if (!matched) return;
 
diff --git a/src/server/api/stream/channels/home-timeline.ts b/src/server/api/stream/channels/home-timeline.ts
index 61960657b42fc3b3900629228031504be19b68b2..9aa4dc1c0f72881d12e814dbd8ef484c238ad714 100644
--- a/src/server/api/stream/channels/home-timeline.ts
+++ b/src/server/api/stream/channels/home-timeline.ts
@@ -2,6 +2,7 @@ import autobind from 'autobind-decorator';
 import shouldMuteThisNote from '../../../../misc/should-mute-this-note';
 import Channel from '../channel';
 import { Notes } from '../../../../models';
+import { PackedNote } from '../../../../models/repositories/note';
 
 export default class extends Channel {
 	public readonly chName = 'homeTimeline';
@@ -15,7 +16,7 @@ export default class extends Channel {
 	}
 
 	@autobind
-	private async onNote(note: any) {
+	private async onNote(note: PackedNote) {
 		// その投稿のユーザーをフォローしていなかったら弾く
 		if (this.user!.id !== note.userId && !this.following.includes(note.userId)) return;
 
diff --git a/src/server/api/stream/channels/hybrid-timeline.ts b/src/server/api/stream/channels/hybrid-timeline.ts
index a8020bfcfa10ef09d9883414125ed7a8d6af4065..a1e5bf238eddef7428fcb2873afad327cf37c084 100644
--- a/src/server/api/stream/channels/hybrid-timeline.ts
+++ b/src/server/api/stream/channels/hybrid-timeline.ts
@@ -3,6 +3,8 @@ import shouldMuteThisNote from '../../../../misc/should-mute-this-note';
 import Channel from '../channel';
 import fetchMeta from '../../../../misc/fetch-meta';
 import { Notes } from '../../../../models';
+import { PackedNote } from '../../../../models/repositories/note';
+import { PackedUser } from '../../../../models/repositories/user';
 
 export default class extends Channel {
 	public readonly chName = 'hybridTimeline';
@@ -19,12 +21,12 @@ export default class extends Channel {
 	}
 
 	@autobind
-	private async onNote(note: any) {
+	private async onNote(note: PackedNote) {
 		// 自分自身の投稿 または その投稿のユーザーをフォローしている または 全体公開のローカルの投稿 の場合だけ
 		if (!(
 			this.user!.id === note.userId ||
 			this.following.includes(note.userId) ||
-			(note.user.host == null && note.visibility === 'public')
+			((note.user as PackedUser).host == null && note.visibility === 'public')
 		)) return;
 
 		if (['followers', 'specified'].includes(note.visibility)) {
diff --git a/src/server/api/stream/channels/local-timeline.ts b/src/server/api/stream/channels/local-timeline.ts
index 4aec2d66b4028cab2234e127a792ef967ec54578..82b957afa4a2a63943d1d93007ea5241b73ae0b2 100644
--- a/src/server/api/stream/channels/local-timeline.ts
+++ b/src/server/api/stream/channels/local-timeline.ts
@@ -3,6 +3,8 @@ import shouldMuteThisNote from '../../../../misc/should-mute-this-note';
 import Channel from '../channel';
 import fetchMeta from '../../../../misc/fetch-meta';
 import { Notes } from '../../../../models';
+import { PackedNote } from '../../../../models/repositories/note';
+import { PackedUser } from '../../../../models/repositories/user';
 
 export default class extends Channel {
 	public readonly chName = 'localTimeline';
@@ -21,8 +23,8 @@ export default class extends Channel {
 	}
 
 	@autobind
-	private async onNote(note: any) {
-		if (note.user.host !== null) return;
+	private async onNote(note: PackedNote) {
+		if ((note.user as PackedUser).host !== null) return;
 		if (note.visibility === 'home') return;
 
 		if (['followers', 'specified'].includes(note.visibility)) {
diff --git a/src/server/api/stream/channels/user-list.ts b/src/server/api/stream/channels/user-list.ts
index f5434b8f0862485f239c7d2f72e4b9c56df04334..119bacf6ece61f22a954977bf820090547c48b12 100644
--- a/src/server/api/stream/channels/user-list.ts
+++ b/src/server/api/stream/channels/user-list.ts
@@ -3,6 +3,7 @@ import Channel from '../channel';
 import { Notes, UserListJoinings } from '../../../../models';
 import shouldMuteThisNote from '../../../../misc/should-mute-this-note';
 import { User } from '../../../../models/entities/user';
+import { PackedNote } from '../../../../models/repositories/note';
 
 export default class extends Channel {
 	public readonly chName = 'userList';
@@ -38,7 +39,7 @@ export default class extends Channel {
 	}
 
 	@autobind
-	private async onNote(note: any) {
+	private async onNote(note: PackedNote) {
 		if (!this.listUsers.includes(note.userId)) return;
 
 		if (['followers', 'specified'].includes(note.visibility)) {
diff --git a/src/services/chart/charts/schemas/active-users.ts b/src/services/chart/charts/schemas/active-users.ts
index da8c63389c80c6d3ea602197a9bfc567ee062724..f10393bc36db5ce3cc42a2de36f958b7c46adce7 100644
--- a/src/services/chart/charts/schemas/active-users.ts
+++ b/src/services/chart/charts/schemas/active-users.ts
@@ -1,9 +1,12 @@
+import { types, bool } from '../../../../misc/schema';
+
 export const logSchema = {
 	/**
 	 * アクティブユーザー数
 	 */
 	count: {
-		type: 'number' as 'number',
+		type: types.number,
+		optional: bool.false, nullable: bool.false,
 		description: 'アクティブユーザー数',
 	},
 };
@@ -12,14 +15,17 @@ export const logSchema = {
  * アクティブユーザーに関するチャート
  */
 export const schema = {
-	type: 'object' as 'object',
+	type: types.object,
+	optional: bool.false, nullable: bool.false,
 	properties: {
 		local: {
-			type: 'object' as 'object',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
 			properties: logSchema
 		},
 		remote: {
-			type: 'object' as 'object',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
 			properties: logSchema
 		},
 	}
diff --git a/src/services/chart/charts/schemas/drive.ts b/src/services/chart/charts/schemas/drive.ts
index 47530e841761037967a62fd00c904fd8852b7215..3327950635ded57fb641daac85fd1d8bde6f2918 100644
--- a/src/services/chart/charts/schemas/drive.ts
+++ b/src/services/chart/charts/schemas/drive.ts
@@ -1,9 +1,12 @@
+import { types, bool } from '../../../../misc/schema';
+
 const logSchema = {
 	/**
 	 * 集計期間時点での、全ドライブファイル数
 	 */
 	totalCount: {
-		type: 'number' as 'number',
+		type: types.number,
+		optional: bool.false, nullable: bool.false,
 		description: '集計期間時点での、全ドライブファイル数'
 	},
 
@@ -11,7 +14,8 @@ const logSchema = {
 	 * 集計期間時点での、全ドライブファイルの合計サイズ
 	 */
 	totalSize: {
-		type: 'number' as 'number',
+		type: types.number,
+		optional: bool.false, nullable: bool.false,
 		description: '集計期間時点での、全ドライブファイルの合計サイズ'
 	},
 
@@ -19,7 +23,8 @@ const logSchema = {
 	 * 増加したドライブファイル数
 	 */
 	incCount: {
-		type: 'number' as 'number',
+		type: types.number,
+		optional: bool.false, nullable: bool.false,
 		description: '増加したドライブファイル数'
 	},
 
@@ -27,7 +32,8 @@ const logSchema = {
 	 * 増加したドライブ使用量
 	 */
 	incSize: {
-		type: 'number' as 'number',
+		type: types.number,
+		optional: bool.false, nullable: bool.false,
 		description: '増加したドライブ使用量'
 	},
 
@@ -35,7 +41,8 @@ const logSchema = {
 	 * 減少したドライブファイル数
 	 */
 	decCount: {
-		type: 'number' as 'number',
+		type: types.number,
+		optional: bool.false, nullable: bool.false,
 		description: '減少したドライブファイル数'
 	},
 
@@ -43,20 +50,24 @@ const logSchema = {
 	 * 減少したドライブ使用量
 	 */
 	decSize: {
-		type: 'number' as 'number',
+		type: types.number,
+		optional: bool.false, nullable: bool.false,
 		description: '減少したドライブ使用量'
 	},
 };
 
 export const schema = {
-	type: 'object' as 'object',
+	type: types.object,
+	optional: bool.false, nullable: bool.false,
 	properties: {
 		local: {
-			type: 'object' as 'object',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
 			properties: logSchema
 		},
 		remote: {
-			type: 'object' as 'object',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
 			properties: logSchema
 		},
 	}
diff --git a/src/services/chart/charts/schemas/federation.ts b/src/services/chart/charts/schemas/federation.ts
index d1d275fc95f5f56450d847260007c6e8c6bd610b..41ae977cbd200a0408981541a3fa7999bacea0a4 100644
--- a/src/services/chart/charts/schemas/federation.ts
+++ b/src/services/chart/charts/schemas/federation.ts
@@ -1,22 +1,29 @@
+import { types, bool } from '../../../../misc/schema';
+
 /**
  * フェデレーションに関するチャート
  */
 export const schema = {
-	type: 'object' as 'object',
+	type: types.object,
+	optional: bool.false, nullable: bool.false,
 	properties: {
 		instance: {
-			type: 'object' as 'object',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
 			properties: {
 				total: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: 'インスタンス数の合計'
 				},
 				inc: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: '増加インスタンス数'
 				},
 				dec: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: '減少インスタンス数'
 				},
 			}
diff --git a/src/services/chart/charts/schemas/hashtag.ts b/src/services/chart/charts/schemas/hashtag.ts
index c1904b67012367dddd73d59ebef158c268b9a21b..918242f66e3cb670345265e8fbc65f318e6514d6 100644
--- a/src/services/chart/charts/schemas/hashtag.ts
+++ b/src/services/chart/charts/schemas/hashtag.ts
@@ -1,9 +1,12 @@
+import { types, bool } from '../../../../misc/schema';
+
 export const logSchema = {
 	/**
 	 * 投稿された数
 	 */
 	count: {
-		type: 'number' as 'number',
+		type: types.number,
+		optional: bool.false, nullable: bool.false,
 		description: '投稿された数',
 	},
 };
@@ -12,14 +15,17 @@ export const logSchema = {
  * ハッシュタグに関するチャート
  */
 export const schema = {
-	type: 'object' as 'object',
+	type: types.object,
+	optional: bool.false, nullable: bool.false,
 	properties: {
 		local: {
-			type: 'object' as 'object',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
 			properties: logSchema
 		},
 		remote: {
-			type: 'object' as 'object',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
 			properties: logSchema
 		},
 	}
diff --git a/src/services/chart/charts/schemas/instance.ts b/src/services/chart/charts/schemas/instance.ts
index 001f2428b58a4398312795418e156bcbb19dae53..d97f49ea7226a5ef5f36c2dd6db6dea3fd8f371e 100644
--- a/src/services/chart/charts/schemas/instance.ts
+++ b/src/services/chart/charts/schemas/instance.ts
@@ -1,58 +1,73 @@
+import { types, bool } from '../../../../misc/schema';
+
 /**
  * インスタンスごとのチャート
  */
 export const schema = {
-	type: 'object' as 'object',
+	type: types.object,
+	optional: bool.false, nullable: bool.false,
 	properties: {
 		requests: {
-			type: 'object' as 'object',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
 			properties: {
 				failed: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: '失敗したリクエスト数'
 				},
 				succeeded: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: '成功したリクエスト数'
 				},
 				received: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: '受信したリクエスト数'
 				},
 			}
 		},
 
 		notes: {
-			type: 'object' as 'object',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
 			properties: {
 				total: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: '集計期間時点での、全投稿数'
 				},
 				inc: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: '増加した投稿数'
 				},
 				dec: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: '減少した投稿数'
 				},
 
 				diffs: {
-					type: 'object' as 'object',
+					type: types.object,
+					optional: bool.false, nullable: bool.false,
 					properties: {
 						normal: {
-							type: 'number' as 'number',
+							type: types.number,
+							optional: bool.false, nullable: bool.false,
 							description: '通常の投稿数の差分'
 						},
 
 						reply: {
-							type: 'number' as 'number',
+							type: types.number,
+							optional: bool.false, nullable: bool.false,
 							description: 'リプライの投稿数の差分'
 						},
 
 						renote: {
-							type: 'number' as 'number',
+							type: types.number,
+							optional: bool.false, nullable: bool.false,
 							description: 'Renoteの投稿数の差分'
 						},
 					}
@@ -61,84 +76,103 @@ export const schema = {
 		},
 
 		users: {
-			type: 'object' as 'object',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
 			properties: {
 				total: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: '集計期間時点での、全ユーザー数'
 				},
 				inc: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: '増加したユーザー数'
 				},
 				dec: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: '減少したユーザー数'
 				},
 			}
 		},
 
 		following: {
-			type: 'object' as 'object',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
 			properties: {
 				total: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: '集計期間時点での、全フォロー数'
 				},
 				inc: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: '増加したフォロー数'
 				},
 				dec: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: '減少したフォロー数'
 				},
 			}
 		},
 
 		followers: {
-			type: 'object' as 'object',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
 			properties: {
 				total: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: '集計期間時点での、全フォロワー数'
 				},
 				inc: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: '増加したフォロワー数'
 				},
 				dec: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: '減少したフォロワー数'
 				},
 			}
 		},
 
 		drive: {
-			type: 'object' as 'object',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
 			properties: {
 				totalFiles: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: '集計期間時点での、全ドライブファイル数'
 				},
 				totalUsage: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: '集計期間時点での、全ドライブファイルの合計サイズ'
 				},
 				incFiles: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: '増加したドライブファイル数'
 				},
 				incUsage: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: '増加したドライブ使用量'
 				},
 				decFiles: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: '減少したドライブファイル数'
 				},
 				decUsage: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: '減少したドライブ使用量'
 				},
 			}
diff --git a/src/services/chart/charts/schemas/network.ts b/src/services/chart/charts/schemas/network.ts
index 4ef530c07cc0ca2f2b0ca426af59f4751afae902..819e2a145e783d0701c6ca5163eb9f64643a5ba3 100644
--- a/src/services/chart/charts/schemas/network.ts
+++ b/src/services/chart/charts/schemas/network.ts
@@ -1,27 +1,35 @@
+import { types, bool } from '../../../../misc/schema';
+
 /**
  * ネットワークに関するチャート
  */
 export const schema = {
-	type: 'object' as 'object',
+	type: types.object,
+	optional: bool.false, nullable: bool.false,
 	properties: {
 		incomingRequests: {
-			type: 'number' as 'number',
+			type: types.number,
+			optional: bool.false, nullable: bool.false,
 			description: '受信したリクエスト数'
 		},
 		outgoingRequests: {
-			type: 'number' as 'number',
+			type: types.number,
+			optional: bool.false, nullable: bool.false,
 			description: '送信したリクエスト数'
 		},
 		totalTime: {
-			type: 'number' as 'number',
+			type: types.number,
+			optional: bool.false, nullable: bool.false,
 			description: '応答時間の合計' // TIP: (totalTime / incomingRequests) でひとつのリクエストに平均でどれくらいの時間がかかったか知れる
 		},
 		incomingBytes: {
-			type: 'number' as 'number',
+			type: types.number,
+			optional: bool.false, nullable: bool.false,
 			description: '合計受信データ量'
 		},
 		outgoingBytes: {
-			type: 'number' as 'number',
+			type: types.number,
+			optional: bool.false, nullable: bool.false,
 			description: '合計送信データ量'
 		},
 	}
diff --git a/src/services/chart/charts/schemas/notes.ts b/src/services/chart/charts/schemas/notes.ts
index 133d1e3730a22c5ab086b8a309b024a595e0b527..aabe49edd91f660b122433ef457f17a4efc528f4 100644
--- a/src/services/chart/charts/schemas/notes.ts
+++ b/src/services/chart/charts/schemas/notes.ts
@@ -1,34 +1,43 @@
+import { types, bool } from '../../../../misc/schema';
+
 const logSchema = {
 	total: {
-		type: 'number' as 'number',
+		type: types.number,
+		optional: bool.false, nullable: bool.false,
 		description: '集計期間時点での、全投稿数'
 	},
 
 	inc: {
-		type: 'number' as 'number',
+		type: types.number,
+		optional: bool.false, nullable: bool.false,
 		description: '増加した投稿数'
 	},
 
 	dec: {
-		type: 'number' as 'number',
+		type: types.number,
+		optional: bool.false, nullable: bool.false,
 		description: '減少した投稿数'
 	},
 
 	diffs: {
-		type: 'object' as 'object',
+		type: types.object,
+		optional: bool.false, nullable: bool.false,
 		properties: {
 			normal: {
-				type: 'number' as 'number',
+				type: types.number,
+				optional: bool.false, nullable: bool.false,
 				description: '通常の投稿数の差分'
 			},
 
 			reply: {
-				type: 'number' as 'number',
+				type: types.number,
+				optional: bool.false, nullable: bool.false,
 				description: 'リプライの投稿数の差分'
 			},
 
 			renote: {
-				type: 'number' as 'number',
+				type: types.number,
+				optional: bool.false, nullable: bool.false,
 				description: 'Renoteの投稿数の差分'
 			},
 		}
@@ -36,14 +45,17 @@ const logSchema = {
 };
 
 export const schema = {
-	type: 'object' as 'object',
+	type: types.object,
+	optional: bool.false, nullable: bool.false,
 	properties: {
 		local: {
-			type: 'object' as 'object',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
 			properties: logSchema
 		},
 		remote: {
-			type: 'object' as 'object',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
 			properties: logSchema
 		},
 	}
diff --git a/src/services/chart/charts/schemas/per-user-drive.ts b/src/services/chart/charts/schemas/per-user-drive.ts
index 713bd7ed845e68ee2d5226c7193f6577d98006e4..62e77951677bae7fe246b2088fdf2ef5d9fb4fce 100644
--- a/src/services/chart/charts/schemas/per-user-drive.ts
+++ b/src/services/chart/charts/schemas/per-user-drive.ts
@@ -1,11 +1,15 @@
+import { types, bool } from '../../../../misc/schema';
+
 export const schema = {
-	type: 'object' as 'object',
+	type: types.object,
+	optional: bool.false, nullable: bool.false,
 	properties: {
 		/**
 		 * 集計期間時点での、全ドライブファイル数
 		 */
 		totalCount: {
-			type: 'number' as 'number',
+			type: types.number,
+			optional: bool.false, nullable: bool.false,
 			description: '集計期間時点での、全ドライブファイル数'
 		},
 
@@ -13,7 +17,8 @@ export const schema = {
 		 * 集計期間時点での、全ドライブファイルの合計サイズ
 		 */
 		totalSize: {
-			type: 'number' as 'number',
+			type: types.number,
+			optional: bool.false, nullable: bool.false,
 			description: '集計期間時点での、全ドライブファイルの合計サイズ'
 		},
 
@@ -21,7 +26,8 @@ export const schema = {
 		 * 増加したドライブファイル数
 		 */
 		incCount: {
-			type: 'number' as 'number',
+			type: types.number,
+			optional: bool.false, nullable: bool.false,
 			description: '増加したドライブファイル数'
 		},
 
@@ -29,7 +35,8 @@ export const schema = {
 		 * 増加したドライブ使用量
 		 */
 		incSize: {
-			type: 'number' as 'number',
+			type: types.number,
+			optional: bool.false, nullable: bool.false,
 			description: '増加したドライブ使用量'
 		},
 
@@ -37,7 +44,8 @@ export const schema = {
 		 * 減少したドライブファイル数
 		 */
 		decCount: {
-			type: 'number' as 'number',
+			type: types.number,
+			optional: bool.false, nullable: bool.false,
 			description: '減少したドライブファイル数'
 		},
 
@@ -45,7 +53,8 @@ export const schema = {
 		 * 減少したドライブ使用量
 		 */
 		decSize: {
-			type: 'number' as 'number',
+			type: types.number,
+			optional: bool.false, nullable: bool.false,
 			description: '減少したドライブ使用量'
 		},
 	}
diff --git a/src/services/chart/charts/schemas/per-user-following.ts b/src/services/chart/charts/schemas/per-user-following.ts
index d6ca1130e0f1f2a8d1239d995c72d06c18bfa74e..e57869e79a99346ec0c9badaf846b2c5efe7ee1f 100644
--- a/src/services/chart/charts/schemas/per-user-following.ts
+++ b/src/services/chart/charts/schemas/per-user-following.ts
@@ -1,15 +1,19 @@
+import { types, bool } from '../../../../misc/schema';
+
 export const logSchema = {
 	/**
 	 * フォローしている
 	 */
 	followings: {
-		type: 'object' as 'object',
+		type: types.object,
+		optional: bool.false, nullable: bool.false,
 		properties: {
 			/**
 			 * フォローしている合計
 			 */
 			total: {
-				type: 'number' as 'number',
+				type: types.number,
+				optional: bool.false, nullable: bool.false,
 				description: 'フォローしている合計',
 			},
 
@@ -17,7 +21,8 @@ export const logSchema = {
 			 * フォローした数
 			 */
 			inc: {
-				type: 'number' as 'number',
+				type: types.number,
+				optional: bool.false, nullable: bool.false,
 				description: 'フォローした数',
 			},
 
@@ -25,7 +30,8 @@ export const logSchema = {
 			 * フォロー解除した数
 			 */
 			dec: {
-				type: 'number' as 'number',
+				type: types.number,
+				optional: bool.false, nullable: bool.false,
 				description: 'フォロー解除した数',
 			},
 		}
@@ -35,13 +41,15 @@ export const logSchema = {
 	 * フォローされている
 	 */
 	followers: {
-		type: 'object' as 'object',
+		type: types.object,
+		optional: bool.false, nullable: bool.false,
 		properties: {
 			/**
 			 * フォローされている合計
 			 */
 			total: {
-				type: 'number' as 'number',
+				type: types.number,
+				optional: bool.false, nullable: bool.false,
 				description: 'フォローされている合計',
 			},
 
@@ -49,7 +57,8 @@ export const logSchema = {
 			 * フォローされた数
 			 */
 			inc: {
-				type: 'number' as 'number',
+				type: types.number,
+				optional: bool.false, nullable: bool.false,
 				description: 'フォローされた数',
 			},
 
@@ -57,7 +66,8 @@ export const logSchema = {
 			 * フォロー解除された数
 			 */
 			dec: {
-				type: 'number' as 'number',
+				type: types.number,
+				optional: bool.false, nullable: bool.false,
 				description: 'フォロー解除された数',
 			},
 		}
@@ -65,14 +75,17 @@ export const logSchema = {
 };
 
 export const schema = {
-	type: 'object' as 'object',
+	type: types.object,
+	optional: bool.false, nullable: bool.false,
 	properties: {
 		local: {
-			type: 'object' as 'object',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
 			properties: logSchema
 		},
 		remote: {
-			type: 'object' as 'object',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
 			properties: logSchema
 		},
 	}
diff --git a/src/services/chart/charts/schemas/per-user-notes.ts b/src/services/chart/charts/schemas/per-user-notes.ts
index 3c448c4cee2464c83706320dcdc7e533b62e8736..76324500739fde3b631b79bdb549cea9df081f34 100644
--- a/src/services/chart/charts/schemas/per-user-notes.ts
+++ b/src/services/chart/charts/schemas/per-user-notes.ts
@@ -1,36 +1,46 @@
+import { types, bool } from '../../../../misc/schema';
+
 export const schema = {
-	type: 'object' as 'object',
+	type: types.object,
+	optional: bool.false, nullable: bool.false,
 	properties: {
 		total: {
-			type: 'number' as 'number',
+			type: types.number,
+			optional: bool.false, nullable: bool.false,
 			description: '集計期間時点での、全投稿数'
 		},
 
 		inc: {
-			type: 'number' as 'number',
+			type: types.number,
+			optional: bool.false, nullable: bool.false,
 			description: '増加した投稿数'
 		},
 
 		dec: {
-			type: 'number' as 'number',
+			type: types.number,
+			optional: bool.false, nullable: bool.false,
 			description: '減少した投稿数'
 		},
 
 		diffs: {
-			type: 'object' as 'object',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
 			properties: {
 				normal: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: '通常の投稿数の差分'
 				},
 
 				reply: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: 'リプライの投稿数の差分'
 				},
 
 				renote: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: 'Renoteの投稿数の差分'
 				},
 			}
diff --git a/src/services/chart/charts/schemas/per-user-reactions.ts b/src/services/chart/charts/schemas/per-user-reactions.ts
index 1278184da65837f810ceb9a0cf122690d1d5d355..df7d5a6dbb11cc8ad701c270831aa666b90c3702 100644
--- a/src/services/chart/charts/schemas/per-user-reactions.ts
+++ b/src/services/chart/charts/schemas/per-user-reactions.ts
@@ -1,9 +1,12 @@
+import { types, bool } from '../../../../misc/schema';
+
 export const logSchema = {
 	/**
 	 * フォローしている合計
 	 */
 	count: {
-		type: 'number' as 'number',
+		type: types.number,
+		optional: bool.false, nullable: bool.false,
 		description: 'リアクションされた数',
 	},
 };
@@ -12,14 +15,17 @@ export const logSchema = {
  * ユーザーごとのリアクションに関するチャート
  */
 export const schema = {
-	type: 'object' as 'object',
+	type: types.object,
+	optional: bool.false, nullable: bool.false,
 	properties: {
 		local: {
-			type: 'object' as 'object',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
 			properties: logSchema
 		},
 		remote: {
-			type: 'object' as 'object',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
 			properties: logSchema
 		},
 	}
diff --git a/src/services/chart/charts/schemas/test-grouped.ts b/src/services/chart/charts/schemas/test-grouped.ts
index acf3fddb3157dbe34cece0a149bf3e92ad736e97..893458e90a17be3bebaca451381c9a4132b67762 100644
--- a/src/services/chart/charts/schemas/test-grouped.ts
+++ b/src/services/chart/charts/schemas/test-grouped.ts
@@ -1,21 +1,28 @@
+import { types, bool } from '../../../../misc/schema';
+
 export const schema = {
-	type: 'object' as 'object',
+	type: types.object,
+	optional: bool.false, nullable: bool.false,
 	properties: {
 		foo: {
-			type: 'object' as 'object',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
 			properties: {
 				total: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: ''
 				},
 
 				inc: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: ''
 				},
 
 				dec: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: ''
 				},
 			}
diff --git a/src/services/chart/charts/schemas/test-unique.ts b/src/services/chart/charts/schemas/test-unique.ts
index 8fcfbf3c72342013e599c06ecf33a3098c898684..2b3f445ff02edcb8c4093285f0717ba48e787bf8 100644
--- a/src/services/chart/charts/schemas/test-unique.ts
+++ b/src/services/chart/charts/schemas/test-unique.ts
@@ -1,8 +1,12 @@
+import { types, bool } from '../../../../misc/schema';
+
 export const schema = {
-	type: 'object' as 'object',
+	type: types.object,
+	optional: bool.false, nullable: bool.false,
 	properties: {
 		foo: {
-			type: 'number' as 'number',
+			type: types.number,
+			optional: bool.false, nullable: bool.false,
 			description: ''
 		},
 	}
diff --git a/src/services/chart/charts/schemas/test.ts b/src/services/chart/charts/schemas/test.ts
index b1344500bfb3140c6bb4362c589161ee6af3ff59..9bdc05990b6a29097278d3fdad1878afe262f52a 100644
--- a/src/services/chart/charts/schemas/test.ts
+++ b/src/services/chart/charts/schemas/test.ts
@@ -1,21 +1,28 @@
+import { types, bool } from '../../../../misc/schema';
+
 export const schema = {
-	type: 'object' as 'object',
+	type: types.object,
+	optional: bool.false, nullable: bool.false,
 	properties: {
 		foo: {
-			type: 'object' as 'object',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
 			properties: {
 				total: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: ''
 				},
 
 				inc: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: ''
 				},
 
 				dec: {
-					type: 'number' as 'number',
+					type: types.number,
+					optional: bool.false, nullable: bool.false,
 					description: ''
 				},
 			}
diff --git a/src/services/chart/charts/schemas/users.ts b/src/services/chart/charts/schemas/users.ts
index db7e2dd057b1e02aa432f6881e2c7db83b53620d..6ae61333503db198e99b9121d4715a7f453f43d4 100644
--- a/src/services/chart/charts/schemas/users.ts
+++ b/src/services/chart/charts/schemas/users.ts
@@ -1,9 +1,12 @@
+import { types, bool } from '../../../../misc/schema';
+
 const logSchema = {
 	/**
 	 * 集計期間時点での、全ユーザー数
 	 */
 	total: {
-		type: 'number' as 'number',
+		type: types.number,
+		optional: bool.false, nullable: bool.false,
 		description: '集計期間時点での、全ユーザー数'
 	},
 
@@ -11,7 +14,8 @@ const logSchema = {
 	 * 増加したユーザー数
 	 */
 	inc: {
-		type: 'number' as 'number',
+		type: types.number,
+		optional: bool.false, nullable: bool.false,
 		description: '増加したユーザー数'
 	},
 
@@ -19,20 +23,24 @@ const logSchema = {
 	 * 減少したユーザー数
 	 */
 	dec: {
-		type: 'number' as 'number',
+		type: types.number,
+		optional: bool.false, nullable: bool.false,
 		description: '減少したユーザー数'
 	},
 };
 
 export const schema = {
-	type: 'object' as 'object',
+	type: types.object,
+	optional: bool.false, nullable: bool.false,
 	properties: {
 		local: {
-			type: 'object' as 'object',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
 			properties: logSchema
 		},
 		remote: {
-			type: 'object' as 'object',
+			type: types.object,
+			optional: bool.false, nullable: bool.false,
 			properties: logSchema
 		},
 	}
diff --git a/src/services/chart/core.ts b/src/services/chart/core.ts
index fe762f2b2452afc6b88a235f78a2d9639a50628f..6a69a21b7ed1f9fd6c0b0343afa3e609dac9a0e4 100644
--- a/src/services/chart/core.ts
+++ b/src/services/chart/core.ts
@@ -8,7 +8,7 @@ import * as moment from 'moment';
 import * as nestedProperty from 'nested-property';
 import autobind from 'autobind-decorator';
 import Logger from '../logger';
-import { Schema } from '../../misc/schema';
+import { Schema, bool, types } from '../../misc/schema';
 import { EntitySchema, getRepository, Repository, LessThan, MoreThanOrEqual } from 'typeorm';
 import { isDuplicateKeyValueError } from '../../misc/is-duplicate-key-value-error';
 
@@ -449,7 +449,8 @@ export function convertLog(logSchema: Schema): Schema {
 	if (v.type === 'number') {
 		v.type = 'array';
 		v.items = {
-			type: 'number'
+			type: types.number,
+			optional: bool.false, nullable: bool.false,
 		};
 	} else if (v.type === 'object') {
 		for (const k of Object.keys(v.properties!)) {
diff --git a/src/services/note/create.ts b/src/services/note/create.ts
index 02e33d6789f999570824f7f27f643c3a5186a3d4..ce229d639379e820ec7398a98fcf33091f0bdcea 100644
--- a/src/services/note/create.ts
+++ b/src/services/note/create.ts
@@ -237,7 +237,7 @@ export default async (user: User, data: Option, silent = false) => new Promise<N
 	const noteObj = await Notes.pack(note);
 
 	if (isFirstNote) {
-		noteObj.isFirstNote = true;
+		(noteObj as any).isFirstNote = true;
 	}
 
 	publishNotesStream(noteObj);
diff --git a/test/streaming.ts b/test/streaming.ts
index 6b9ef9cea5bac18f47ecd7e0694b9b16c7661677..11c63cd0f59a99537f048644af1a43d0c82111cd 100644
--- a/test/streaming.ts
+++ b/test/streaming.ts
@@ -628,7 +628,7 @@ describe('Streaming', () => {
 
 			// リスト作成
 			const list = await request('/users/lists/create', {
-				title: 'my list'
+				name: 'my list'
 			}, alice).then(x => x.body);
 
 			// Alice が Bob をリスイン
@@ -658,7 +658,7 @@ describe('Streaming', () => {
 
 			// リスト作成
 			const list = await request('/users/lists/create', {
-				title: 'my list'
+				name: 'my list'
 			}, alice).then(x => x.body);
 
 			let fired = false;
@@ -689,7 +689,7 @@ describe('Streaming', () => {
 
 			// リスト作成
 			const list = await request('/users/lists/create', {
-				title: 'my list'
+				name: 'my list'
 			}, alice).then(x => x.body);
 
 			// Alice が Bob をリスイン
@@ -724,7 +724,7 @@ describe('Streaming', () => {
 
 			// リスト作成
 			const list = await request('/users/lists/create', {
-				title: 'my list'
+				name: 'my list'
 			}, alice).then(x => x.body);
 
 			// Alice が Bob をリスイン