REST Client
The REST client provides typed HTTP requests to the Heimdall API.
apiRequest
Make an authenticated REST request. The first argument is always an
ApiClientConfig — pass getApiConfig() from @/lib/api.
import { getApiConfig, apiRequest } from "@/lib/api";
import type { ApiResponse } from "@/lib/api";
const response: ApiResponse<User> = await apiRequest<User>(getApiConfig(), "/v1/users/123");
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
config | ApiClientConfig | Yes | API client config (baseUrl, optional systemApiKey) — use getApiConfig() |
endpoint | string | Yes | API endpoint (e.g., /v1/users/123) |
options | ApiRequestOptions | No | Request options |
Options
interface ApiRequestOptions {
method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
body?: unknown;
headers?: Record<string, string>;
accessToken?: string;
userAgent?: string;
clientIp?: string;
sourceService?: string;
}
| Option | Type | Default | Description |
|---|---|---|---|
method | string | "GET" | HTTP method |
body | unknown | - | Request body (auto-serialized to JSON) |
headers | Record<string, string> | - | Additional headers |
accessToken | string | - | Override auth token |
userAgent | string | - | Original client User-Agent (forwarded as X-Original-User-Agent) |
clientIp | string | - | Original client IP (forwarded as X-Forwarded-For) |
sourceService | string | - | Source service (sent as X-Source-Service) |
Response
interface ApiResponse<T> {
data?: T;
error?: string;
status: number;
}
Examples
GET Request
import { getApiConfig, apiRequest } from "@/lib/api";
const response = await apiRequest<UserProfile>(getApiConfig(), "/v1/users/123/profile");
if (response.error) {
console.error("Error:", response.error);
return;
}
console.log("User:", response.data);
POST Request
const response = await apiRequest<CreateUserResponse>(getApiConfig(), "/v1/users", {
method: "POST",
body: {
email: "user@example.com",
name: "John Doe",
},
});
if (response.status === 201) {
console.log("User created:", response.data);
}
PUT Request with Auth Override
const response = await apiRequest<void>(getApiConfig(), "/v1/users/123", {
method: "PUT",
body: { name: "New Name" },
accessToken: userAccessToken,
});
DELETE Request
const response = await apiRequest<void>(getApiConfig(), "/v1/users/123", {
method: "DELETE",
});
if (response.status === 204) {
console.log("User deleted");
}
Error Handling
The client handles errors gracefully and returns them in the response:
const response = await apiRequest<User>(getApiConfig(), "/v1/users/invalid");
if (response.error) {
switch (response.status) {
case 400:
console.error("Bad request:", response.error);
break;
case 401:
console.error("Unauthorized");
break;
case 404:
console.error("User not found");
break;
case 500:
console.error("Server error:", response.error);
break;
}
}
Client Info & Audit Logging
The REST client also supports client info extraction for audit logging:
import { getApiConfig, apiRequest, extractClientInfo } from "@/lib/api";
import { NextRequest } from "next/server";
export async function POST(request: NextRequest) {
const clientInfo = extractClientInfo(request);
const response = await apiRequest<Result>(getApiConfig(), "/v1/auth/login", {
method: "POST",
body: { email, password },
...clientInfo, // Includes userAgent and clientIp
});
}
To tag the source service, pass sourceService in the options (the library does not
read any SOURCE_SERVICE env var). See the GraphQL Client docs for details.
Pre-built Routes
The library includes pre-built route functions for common operations. Each takes the
ApiClientConfig as its first argument:
import {
// User routes
getUserProfile,
getUserPermissions,
getUserAccounts,
checkUserExists,
// Session routes
getActiveSessions,
revokeSession,
revokeAllOtherSessions,
// Audit routes
getMyAuditLog,
reportAuditEvent,
} from "@elcto/api";
import { getApiConfig } from "@/lib/api";
// Get user profile (wrapped in ApiResponse — use .data)
const profile = await getUserProfile(getApiConfig(), "user-123");
console.log(profile.data?.name);
// Get user permissions (wrapped in ApiResponse — use .data)
const permissions = await getUserPermissions(getApiConfig(), "user-123");
console.log(permissions.data?.is_super_admin);
// Get active sessions (second arg is the current session token, not a userId)
const { sessions } = await getActiveSessions(getApiConfig(), currentToken);
// Get activity log
const auditPage = await getMyAuditLog(getApiConfig(), { page: 1, limit: 20 });
See the Pre-built Routes documentation for complete reference.