Skip to main content

REST Client

The REST client provides typed HTTP requests to the Heimdall API.

apiRequest

Make an authenticated REST request.

import { apiRequest } from "@/lib/api";
import type { ApiResponse } from "@/lib/api";

const response: ApiResponse<User> = await apiRequest<User>("/v1/users/123");

Parameters

ParameterTypeRequiredDescription
endpointstringYesAPI endpoint (e.g., /v1/users/123)
optionsApiRequestOptionsNoRequest options

Options

interface ApiRequestOptions {
method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
body?: unknown;
headers?: Record<string, string>;
accessToken?: string;
}
OptionTypeDefaultDescription
methodstring"GET"HTTP method
bodyunknown-Request body (auto-serialized to JSON)
headersRecord<string, string>-Additional headers
accessTokenstring-Override auth token

Response

interface ApiResponse<T> {
data?: T;
error?: string;
status: number;
}

Examples

GET Request

const response = await apiRequest<UserProfile>("/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>("/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>("/v1/users/123", {
method: "PUT",
body: { name: "New Name" },
accessToken: userAccessToken,
});

DELETE Request

const response = await apiRequest<void>("/v1/users/123", {
method: "DELETE",
});

if (response.status === 204) {
console.log("User deleted");
}

restConfig

Configuration object for the REST client.

import { restConfig } from "@/lib/api";

console.log(restConfig.apiUrl); // "http://localhost:3000"
console.log(restConfig.hasSystemKey); // true/false

Error Handling

The client handles errors gracefully and returns them in the response:

const response = await apiRequest<User>("/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 { 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>("/v1/auth/login", {
method: "POST",
body: { email, password },
...clientInfo, // Includes userAgent and clientIp
});
}

The SOURCE_SERVICE environment variable is automatically included in requests. See the GraphQL Client docs for more details.

Pre-built Routes

The library includes pre-built route functions for common operations:

import {
// User routes
getUserProfile,
getUserPermissions,
getUserAccounts,
checkUserExists,
// Session routes
getActiveSessions,
revokeSession,
revokeAllOtherSessions,
// Audit routes
getMyAuditLog,
reportAuditEvent,
} from "@elcto/api";

// Get user profile
const profile = await getUserProfile("user-123");

// Get user permissions
const permissions = await getUserPermissions("user-123");

// Get active sessions
const { sessions } = await getActiveSessions("user-123");

// Get activity log
const auditPage = await getMyAuditLog({ page: 1, limit: 20 });

See the Pre-built Routes documentation for complete reference.