Api not running

hey!, I am trying to create a api. What i have so far:
const client = new SapphireClient({
defaultPrefix: '!',
caseInsensitiveCommands: true,
logger: {
level: LogLevel.Debug
},
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent
],
loadMessageCommandListeners: true,
api: {
prefix: '/api/',
origin: '*',
automaticallyConnect: true,
auth: {
id: process.env.DISCORD_CLIENT_ID as string,
secret: process.env.DISCORD_CLIENT_SECRET as string,
cookie: 'SAPPHIRE_AUTH',
redirect: process.env.DISCORD_REDIRECT_URI,
scopes: [OAuth2Scopes.Identify, OAuth2Scopes.Guilds],
domainOverwrite: process.env.NODE_ENV === 'development' ? '127.0.0.1' : undefined,
transformers: [transformOauthGuilds]
},
listenOptions: {
port: 3000
}
}
});
const client = new SapphireClient({
defaultPrefix: '!',
caseInsensitiveCommands: true,
logger: {
level: LogLevel.Debug
},
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent
],
loadMessageCommandListeners: true,
api: {
prefix: '/api/',
origin: '*',
automaticallyConnect: true,
auth: {
id: process.env.DISCORD_CLIENT_ID as string,
secret: process.env.DISCORD_CLIENT_SECRET as string,
cookie: 'SAPPHIRE_AUTH',
redirect: process.env.DISCORD_REDIRECT_URI,
scopes: [OAuth2Scopes.Identify, OAuth2Scopes.Guilds],
domainOverwrite: process.env.NODE_ENV === 'development' ? '127.0.0.1' : undefined,
transformers: [transformOauthGuilds]
},
listenOptions: {
port: 3000
}
}
});
and
$schema: "./node_modules/@sapphire/cli/templates/schemas/.sapphirerc.scheme.json"
projectLanguage: "ts"
locations:
base: src
arguments: arguments
commands: commands
listeners: listeners
preconditions: preconditions
interaction-handlers: interaction-handlers
routes: api
customFileTemplates:
enabled: false
location: ""
$schema: "./node_modules/@sapphire/cli/templates/schemas/.sapphirerc.scheme.json"
projectLanguage: "ts"
locations:
base: src
arguments: arguments
commands: commands
listeners: listeners
preconditions: preconditions
interaction-handlers: interaction-handlers
routes: api
customFileTemplates:
enabled: false
location: ""
20 Replies
Marawan
MarawanOP15h ago
the problem is its not running i also have api dir which have
import { authenticated } from '../lib/api/decorators';
import { ApplyOptions } from '@sapphire/decorators';
import { ApiRequest, ApiResponse, HttpCodes, Route } from '@sapphire/plugin-api';

@ApplyOptions<Route.Options>({
route: 'me'
})
export class UserRoute extends Route {
public run(request: ApiRequest, response: ApiResponse) {
const method = request.method?.toUpperCase() ?? 'GET';

if (method === 'GET') {
return this.get(request, response);
}

return response.error(HttpCodes.MethodNotAllowed);
}

@authenticated()
public async get(_request: ApiRequest, response: ApiResponse) {
const authData = _request.auth!;

try {
const userData = await this.container.server.auth!.fetchData(authData.token);

return response.json({
user: userData.user,
guilds: userData.guilds
});
} catch (error: any) {
this.container.logger.error('Error fetching user data in /me route:', error);
if (error.message?.includes('Invalid OAuth2 access token')) {
return response.status(HttpCodes.Unauthorized).json({ message: 'Invalid or expired token. Please re-authenticate.' });
}
return response.status(HttpCodes.InternalServerError).json({ message: 'Failed to fetch user data.' });
}
}
}
import { authenticated } from '../lib/api/decorators';
import { ApplyOptions } from '@sapphire/decorators';
import { ApiRequest, ApiResponse, HttpCodes, Route } from '@sapphire/plugin-api';

@ApplyOptions<Route.Options>({
route: 'me'
})
export class UserRoute extends Route {
public run(request: ApiRequest, response: ApiResponse) {
const method = request.method?.toUpperCase() ?? 'GET';

if (method === 'GET') {
return this.get(request, response);
}

return response.error(HttpCodes.MethodNotAllowed);
}

@authenticated()
public async get(_request: ApiRequest, response: ApiResponse) {
const authData = _request.auth!;

try {
const userData = await this.container.server.auth!.fetchData(authData.token);

return response.json({
user: userData.user,
guilds: userData.guilds
});
} catch (error: any) {
this.container.logger.error('Error fetching user data in /me route:', error);
if (error.message?.includes('Invalid OAuth2 access token')) {
return response.status(HttpCodes.Unauthorized).json({ message: 'Invalid or expired token. Please re-authenticate.' });
}
return response.status(HttpCodes.InternalServerError).json({ message: 'Failed to fetch user data.' });
}
}
}
Favna
Favna15h ago
first of all name the file .get.ts and the method will only ever be a GET request. and what do you mean "not running". have you tried sending a curl to localhost:3000? what does it give as response?
Marawan
MarawanOP14h ago
like that? index.get.ts:
import { Route } from '@sapphire/plugin-api'

export class UserRoute extends Route {
public run(_req: Route.Request, res: Route.Response) {
return res.json({ ok: true })
}
}
import { Route } from '@sapphire/plugin-api'

export class UserRoute extends Route {
public run(_req: Route.Request, res: Route.Response) {
return res.json({ ok: true })
}
}
Favna
Favna14h ago
yes
Marawan
MarawanOP14h ago
PS E:\dev\kate> curl -v http://localhost:3000/api * Host localhost:3000 was resolved. * IPv6: ::1 * IPv4: 127.0.0.1 * Trying [::1]:3000... * Trying 127.0.0.1:3000... * connect to ::1 port 3000 from :: port 53881 failed: Connection refused * connect to 127.0.0.1 port 3000 from 0.0.0.0 port 53882 failed: Connection refused * Failed to connect to localhost port 3000 after 2251 ms: Could not connect to server * closing connection #0 curl: (7) Failed to connect to localhost port 3000 after 2251 ms: Could not connect to server PS E:\dev\kate>
Favna
Favna14h ago
if that is in the routes directory thate would be localhost:300/api/
Marawan
MarawanOP14h ago
still
PS E:\dev\kate> curl -v http://localhost:3000/api/
* Host localhost:3000 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
* Trying [::1]:3000...
* Trying 127.0.0.1:3000...
* connect to ::1 port 3000 from :: port 53891 failed: Connection refused
* connect to 127.0.0.1 port 3000 from 0.0.0.0 port 53892 failed: Connection refused
* Failed to connect to localhost port 3000 after 2252 ms: Could not connect to server
* closing connection #0
curl: (7) Failed to connect to localhost port 3000 after 2252 ms: Could not connect to server
PS E:\dev\kate>
PS E:\dev\kate> curl -v http://localhost:3000/api/
* Host localhost:3000 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
* Trying [::1]:3000...
* Trying 127.0.0.1:3000...
* connect to ::1 port 3000 from :: port 53891 failed: Connection refused
* connect to 127.0.0.1 port 3000 from 0.0.0.0 port 53892 failed: Connection refused
* Failed to connect to localhost port 3000 after 2252 ms: Could not connect to server
* closing connection #0
curl: (7) Failed to connect to localhost port 3000 after 2252 ms: Could not connect to server
PS E:\dev\kate>
that's weird
Favna
Favna14h ago
sec
Marawan
MarawanOP14h ago
tyt
Favna
Favna14h ago
try setting just / as prefix or hm
Marawan
MarawanOP14h ago
same issue
api: {
prefix: '/',
origin: 'http://127.0.0.1:3000',
automaticallyConnect: false,
auth: {
id: process.env.DISCORD_CLIENT_ID as string,
secret: process.env.DISCORD_CLIENT_SECRET as string,
cookie: 'SAPPHIRE_AUTH',
redirect: process.env.DISCORD_REDIRECT_URI,
scopes: [OAuth2Scopes.Identify, OAuth2Scopes.Guilds],
domainOverwrite: process.env.NODE_ENV === 'development' ? '127.0.0.1' : undefined,
transformers: [transformOauthGuilds]
},
listenOptions: {
port: 3000
}
}
api: {
prefix: '/',
origin: 'http://127.0.0.1:3000',
automaticallyConnect: false,
auth: {
id: process.env.DISCORD_CLIENT_ID as string,
secret: process.env.DISCORD_CLIENT_SECRET as string,
cookie: 'SAPPHIRE_AUTH',
redirect: process.env.DISCORD_REDIRECT_URI,
scopes: [OAuth2Scopes.Identify, OAuth2Scopes.Guilds],
domainOverwrite: process.env.NODE_ENV === 'development' ? '127.0.0.1' : undefined,
transformers: [transformOauthGuilds]
},
listenOptions: {
port: 3000
}
}
the funny thing is
if (client.server) {
client.logger.info(`API server is running on http://localhost:${client.options.api?.listenOptions?.port || 3000}/api/`);
} else {
client.logger.warn('API server is not running');
}
if (client.server) {
client.logger.info(`API server is running on http://localhost:${client.options.api?.listenOptions?.port || 3000}/api/`);
} else {
client.logger.warn('API server is not running');
}
actually works. and it saying 2025-04-25 20:28:43 - INFO - API server is running on http://localhost:3000/api/ YO i got it
import { ApplyOptions } from '@sapphire/decorators';
import { Events, Listener } from '@sapphire/framework';

@ApplyOptions<Listener.Options>({ once: true, event: Events.ShardReady })
export class UserShardEvent extends Listener<typeof Events.ShardReady> {
public async run(id: number, _unavailableGuilds: Set<string> | undefined) {
if (id === 0) {
await this.container.server.connect();
}
}
}
import { ApplyOptions } from '@sapphire/decorators';
import { Events, Listener } from '@sapphire/framework';

@ApplyOptions<Listener.Options>({ once: true, event: Events.ShardReady })
export class UserShardEvent extends Listener<typeof Events.ShardReady> {
public async run(id: number, _unavailableGuilds: Set<string> | undefined) {
if (id === 0) {
await this.container.server.connect();
}
}
}
this bitch idk if this related but it now saying {"ok":true} now the routes not working omfg
Favna
Favna14h ago
that's weird though, that should be automatic with the automaticallyConnect which is also true by default btw
Marawan
MarawanOP14h ago
it was false lmao
Favna
Favna14h ago
you had it true here
Marawan
MarawanOP14h ago
yeah ur right, its now working now the route should be /me? right? because prefix is /
Favna
Favna14h ago
yeah you can change it back to /api/ yeah so with prefix of /api/ both /api and /api/ should work I had some trouble setting up my test bot where I apparently didnt upgrade the plugin correctly before
Favna
Favna14h ago
api: {
prefix: '/api/',
origin: '*',
automaticallyConnect: true,
auth: {
id: 'auth_id',
secret: 'auth_secret',
cookie: 'SAPPHIRE_AUTH',
redirect: 'redirect_uri',
scopes: [OAuth2Scopes.Identify, OAuth2Scopes.Guilds],
domainOverwrite: process.env.NODE_ENV === 'development' ? '127.0.0.1' : undefined
},
listenOptions: { port: 3000 }
},
api: {
prefix: '/api/',
origin: '*',
automaticallyConnect: true,
auth: {
id: 'auth_id',
secret: 'auth_secret',
cookie: 'SAPPHIRE_AUTH',
redirect: 'redirect_uri',
scopes: [OAuth2Scopes.Identify, OAuth2Scopes.Guilds],
domainOverwrite: process.env.NODE_ENV === 'development' ? '127.0.0.1' : undefined
},
listenOptions: { port: 3000 }
},
No description
No description
Favna
Favna14h ago
anyway you only need to set automaticallyConnect to false and check for shard id if you use a third party library for sharding. You dont need to do that for DiscordJS internal sharder and if you dont do sharding at all then you really dont need to
Marawan
MarawanOP14h ago
ohh yeah i get it thank you so much fuck, shapphire is perfect lmao
Favna
Favna14h ago
❤️

Did you find this page helpful?