arkynChangelogGuides
docs / services / api-service

ApiService

The ApiService is a class that provides a simple and consistent interface for making HTTP requests to REST APIs. It supports all common HTTP methods (GET, POST, PUT, PATCH, DELETE), automatic header management, token-based authentication, and optional debug logging.

Import

ts

import { ApiService } from "@arkyn/server/apiService";
Learn how subpath and root imports differ in How do I use imports.

Constructor

Creates a new ApiService instance with the provided configuration.
  • baseUrl (required): The base URL for all API requests. This will be prepended to all endpoint paths.
  • baseHeaders (optional): Default headers to include in every request. These can be overridden by request-specific headers.
  • baseToken (optional): A default Bearer token for authorization. This can be overridden by request-specific tokens.
  • enableDebug (optional): Enable debug logging for requests. When true, request details will be logged using flushDebugLogs. Default is false.

typescript

const api = new ApiService({
baseUrl: "https://api.example.com",
baseHeaders: { "Content-Type": "application/json" },
baseToken: "your-api-token",
enableDebug: true,
});

Methods

All methods return a Promise with the API response containing:
  • success: A boolean indicating whether the request was successful.
  • status: The HTTP status code of the response.
  • message: A message describing the result of the request.
  • response: The parsed response payload (generic type T).
  • cause: Additional error information, if applicable (string | Error | null).
get(endpoint, data?) - Sends a GET request to the specified endpoint.
post(endpoint, data?) - Sends a POST request with an optional body.
put(endpoint, data?) - Sends a PUT request with an optional body.
patch(endpoint, data?) - Sends a PATCH request with an optional body.
delete(endpoint, data?) - Sends a DELETE request with an optional body.

Request data options

For GET requests:
  • headers: Additional headers for this request
  • token: Bearer token (overrides baseToken)
  • urlParams: Values substituted into :paramName placeholders in the endpoint path (not appended as a query string)
For POST, PUT, PATCH, DELETE requests:
  • body: Request body (any serializable data)
  • headers: Additional headers for this request
  • token: Bearer token (overrides baseToken)
  • urlParams: Values substituted into :paramName placeholders in the endpoint path (not appended as a query string)

Usage example

typescript

import { ApiService } from "@arkyn/server/apiService";
const api = new ApiService({
baseUrl: "https://api.example.com",
baseHeaders: { "Content-Type": "application/json" },
enableDebug: process.env.NODE_ENV === "development",
});
// GET request with a route variable
const user = await api.get("/users/:id", {
urlParams: { id: "42" },
});
// GET request with custom token
const profile = await api.get("/me", {
token: "user-specific-token",
});
// POST request with body
const newUser = await api.post("/users", {
body: { name: "John", email: "john@example.com" },
});
// PUT request
const updatedUser = await api.put("/users/:userId", {
body: { name: "John Doe" },
urlParams: { userId: "123" },
});
// PATCH request
const patchedUser = await api.patch("/users/:userId", {
body: { status: "active" },
urlParams: { userId: "123" },
});
// DELETE request
const deleted = await api.delete("/users/:userId", {
urlParams: { userId: "123" },
});
// Handling responses
if (user.status === 200) {
console.log(user.response); // Response data
} else {
console.log(user.message); // Error message
}

Header priority

Headers are merged in the following order (later values override earlier ones):
  1. baseToken (as Authorization: Bearer {token})
  2. baseHeaders (from constructor)
  3. headers (from request data)
  4. token (from request data, as Authorization: Bearer {token})
Note: Content-Type is always forced to application/json by the client after the headers above are merged, so it cannot be overridden via baseHeaders or per-request headers.

Debug output

When enableDebug is enabled, each request logs the following information:
  • Base URL
  • Endpoint
  • HTTP method and response status
  • Response message
  • Headers (if present)
  • Request body (if present)
Debug logs are output using flushDebugLogs with the "yellow" color scheme.

Route variables

Replaces placeholders in the URL path (e.g., /users/:userId becomes /users/123)
Using route variables with :param syntax is optional, but recommended when integrating with LogService. The log system generates logs based on URLs, so having a consistent base URL with variables as route parameters makes logs more readable and aggregatable.

typescript

// Without route variables - each userId creates a different log entry
await api.get("/users/123");
await api.get("/users/456");
// Logs: GET /users/123, GET /users/456
// With route variables - logs are grouped by the base pattern
await api.get("/users/:userId", { urlParams: { userId: "123" } });
await api.get("/users/:userId", { urlParams: { userId: "456" } });
// Logs: GET /users/:userId (with userId as metadata)

Notes

The service automatically prepends the baseUrl to all endpoint paths, so endpoints should start with /.
All methods are async and should be awaited. The response object always contains success, status, message, response, and cause properties.
Related in Services
On this page
    arkyn