diff --git a/packages/backend/src/server/api/ApiCallService.ts b/packages/backend/src/server/api/ApiCallService.ts
index 415fbf08dd..c19e861a5a 100644
--- a/packages/backend/src/server/api/ApiCallService.ts
+++ b/packages/backend/src/server/api/ApiCallService.ts
@@ -271,6 +271,17 @@ export class ApiCallService implements OnApplicationShutdown {
 			}
 		}
 
+		if (ep.meta.requireRoleOption != null && !user!.isRoot) {
+			const myRole = await this.roleService.getUserRoleOptions(user!.id);
+			if (!myRole[ep.meta.requireRoleOption]) {
+				throw new ApiError({
+					message: 'You are not assigned to a required role.',
+					code: 'ROLE_PERMISSION_DENIED',
+					id: '7f86f06f-7e15-4057-8561-f4b6d4ac755a',
+				});
+			}
+		}
+
 		if (token && ep.meta.kind && !token.permission.some(p => p === ep.meta.kind)) {
 			throw new ApiError({
 				message: 'Your app does not have the necessary permissions to use this endpoint.',
diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts
index 0a26094c44..f50a3b5dd2 100644
--- a/packages/backend/src/server/api/endpoints.ts
+++ b/packages/backend/src/server/api/endpoints.ts
@@ -695,6 +695,8 @@ export interface IEndpointMeta {
 	 */
 	readonly requireAdmin?: boolean;
 
+	readonly requireRoleOption?: string;
+
 	/**
 	 * エンドポイントのリミテーションに関するやつ
 	 * 省略した場合はリミテーションは無いものとして解釈されます。
diff --git a/packages/backend/src/server/api/endpoints/invite.ts b/packages/backend/src/server/api/endpoints/invite.ts
index d22946e04a..9b03cf4bb6 100644
--- a/packages/backend/src/server/api/endpoints/invite.ts
+++ b/packages/backend/src/server/api/endpoints/invite.ts
@@ -4,12 +4,12 @@ import { Endpoint } from '@/server/api/endpoint-base.js';
 import type { RegistrationTicketsRepository } from '@/models/index.js';
 import { IdService } from '@/core/IdService.js';
 import { DI } from '@/di-symbols.js';
-import { RoleService } from '@/core/RoleService.js';
 
 export const meta = {
 	tags: ['meta'],
 
 	requireCredential: true,
+	requireRoleOption: 'canInvite',
 
 	res: {
 		type: 'object',
@@ -39,15 +39,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 		@Inject(DI.registrationTicketsRepository)
 		private registrationTicketsRepository: RegistrationTicketsRepository,
 
-		private roleService: RoleService,
 		private idService: IdService,
 	) {
 		super(meta, paramDef, async (ps, me) => {
-			const role = await this.roleService.getUserRoleOptions(me.id);
-			if (!me.isRoot && !role.canInvite) {
-				throw new Error('access denied');
-			}
-
 			const code = rndstr({
 				length: 8,
 				chars: '2-9A-HJ-NP-Z', // [0-9A-Z] w/o [01IO] (32 patterns)