SurrealDB
SurrealDB Docs Logo

Enter a search query

Navigation

SurrealApi

The SurrealApi class exposes methods to interact with user-defined API endpoints in SurrealDB. It provides type-safe HTTP-style methods (GET, POST, PUT, DELETE, PATCH, TRACE) for invoking custom database APIs.

Source: api/api.ts

Overview

SurrealApi allows you to access custom API endpoints defined in your SurrealDB database. The class supports type-safe API definitions for better development experience.

// Define your API paths with types type MyPaths = { "/users": { get: [void, User[]] }; "/users/:id": { get: [void, User] }; "/users": { post: [CreateUserInput, User] }; }; // Access with type safety const api = db.api<MyPaths>(); const users = await api.get("/users"); // Type: User[]

Creating an API Instance

API instances are created through the api property on Surreal, SurrealSession, or SurrealTransaction:

// Basic API access const api = db.api(); // Type-safe API access const api = db.api<MyPaths>(); // API with path prefix const usersApi = db.api<MyPaths>("/users");

Type Definitions

PathDef

Defines the HTTP methods available for an API path:

type PathDef = Partial<Record<HttpMethod, MethodDef>>; type HttpMethod = "get" | "post" | "put" | "delete" | "patch" | "trace"; type MethodDef = [RequestBody, ResponseBody] | [];

Example Path Definitions

type MyApiPaths = { // GET endpoint with no request body, returns User[] "/users": { get: [void, User[]]; post: [CreateUserRequest, User]; }; // Dynamic path parameters [K: `/users/${string}`]: { get: [void, User]; put: [UpdateUserRequest, User]; delete: [void, void]; }; // POST endpoint with request/response bodies "/auth/login": { post: [{ email: string; password: string }, { token: string }]; }; };

Methods

Configure a header for all requests sent by this API instance. Useful for setting common headers like authentication tokens or content types.

Method Syntax
api.header(name, value)

Parameters

ParameterTypeDescription
name requiredstringThe name of the header to configure.
value requiredstring | nullThe value to set, or null to remove the header.

Returns

void

Examples

Set Custom Header
api.header('X-API-Key', 'my-secret-key');
Remove Header
api.header('X-API-Key', null);
Set Authorization Header
api.header('Authorization', `Bearer ${token}`);

.invoke()

Invoke a user-defined API with a custom request object. This is the generic method used by all HTTP method-specific functions.

Tip

Prefer using method-specific functions (.get(), .post(), etc.) for better type safety.

Method Syntax
api.invoke<Req, Res>(path, request?)

Parameters

ParameterTypeDescription
path requiredstringThe API path to invoke.
request optionalApiRequest<Req>The request configuration object.

Returns

ApiPromise<Req, Res> - A promise for the API response

Example

const result = await api.invoke('/custom', { method: 'post', body: { data: 'value' }, headers: { 'X-Custom': 'header' }, query: { filter: 'active' } });

.get()

Invoke a user-defined GET API endpoint.

Method Syntax
api.get(path)

Parameters

ParameterTypeDescription
path requiredP extends ValidPaths<TPaths, “get”>The API path to invoke.

Returns

ApiPromise<void, ResponseBody> - A promise for the GET response

Examples

Get All Users
const users = await api.get("/users");
Get Specific User
const user = await api.get("/users/123");

.post()

Invoke a user-defined POST API endpoint.

Method Syntax
api.post(path, body?)

Parameters

ParameterTypeDescription
path requiredP extends ValidPaths<TPaths, “post”>The API path to invoke.
body optionalRequestBody<TPaths, P, “post”>The request body to send.

Returns

ApiPromise<RequestBody, ResponseBody> - A promise for the POST response

Example

const newUser = await api.post("/users", { name: "John Doe", email: "john@example.com" });

.put()

Invoke a user-defined PUT API endpoint.

Method Syntax
api.put(path, body?)

Parameters

ParameterTypeDescription
path requiredP extends ValidPaths<TPaths, “put”>The API path to invoke.
body optionalRequestBody<TPaths, P, “put”>The request body to send.

Returns

ApiPromise<RequestBody, ResponseBody> - A promise for the PUT response

Example

const updated = await api.put("/users/123", { name: "John Smith", email: "john.smith@example.com" });

.delete()

Invoke a user-defined DELETE API endpoint.

Method Syntax
api.delete(path, body?)

Parameters

ParameterTypeDescription
path requiredP extends ValidPaths<TPaths, “delete”>The API path to invoke.
body optionalRequestBody<TPaths, P, “delete”>Optional request body.

Returns

ApiPromise<RequestBody, ResponseBody> - A promise for the DELETE response

Example

await api.delete("/users/123");

.patch()

Invoke a user-defined PATCH API endpoint.

Method Syntax
api.patch(path, body?)

Parameters

ParameterTypeDescription
path requiredP extends ValidPaths<TPaths, “patch”>The API path to invoke.
body optionalRequestBody<TPaths, P, “patch”>The partial updates to apply.

Returns

ApiPromise<RequestBody, ResponseBody> - A promise for the PATCH response

Example

const updated = await api.patch("/users/123", { email: "newemail@example.com" });

.trace()

Invoke a user-defined TRACE API endpoint.

Method Syntax
api.trace(path, body?)

Parameters

ParameterTypeDescription
path requiredP extends ValidPaths<TPaths, “trace”>The API path to invoke.
body optionalRequestBody<TPaths, P, “trace”>Optional request body.

Returns

ApiPromise<RequestBody, ResponseBody> - A promise for the TRACE response

Complete Examples

Basic API Usage

import { Surreal } from 'surrealdb'; const db = new Surreal(); await db.connect('ws://localhost:8000'); // Get API instance const api = db.api(); // Make API calls const users = await api.get('/users'); const user = await api.get('/users/123'); const created = await api.post('/users', { name: 'New User', email: 'user@example.com' });

Type-Safe API

// Define your API contract type ApiPaths = { "/users": { get: [void, User[]]; post: [CreateUserRequest, User]; }; [K: `/users/${string}`]: { get: [void, User]; put: [UpdateUserRequest, User]; delete: [void, void]; }; "/auth/login": { post: [LoginRequest, LoginResponse]; }; }; // Create type-safe API instance const api = db.api<ApiPaths>(); // All calls are type-checked const users: User[] = await api.get("/users"); const user: User = await api.get("/users/123"); const newUser: User = await api.post("/users", { name: "Alice", email: "alice@example.com" });

Using Headers

const api = db.api(); // Set authentication header const token = await login(); api.header('Authorization', `Bearer ${token}`); // All subsequent requests include the header const protected Data = await api.get('/protected-endpoint'); // Remove header api.header('Authorization', null);

API with Prefix

type UserPaths = { "/": { get: [void, User[]] }; [K: `/${string}`]: { get: [void, User]; put: [UpdateUserRequest, User]; delete: [void, void]; }; }; // Create API with prefix const usersApi = db.api<UserPaths>("/users"); // Calls are prefixed automatically const all Users = await usersApi.get("/"); // GET /users/ const user = await usersApi.get("/123"); // GET /users/123 const updated = await usersApi.put("/123", data); // PUT /users/123

Error Handling

const api = db.api(); try { const user = await api.get('/users/999'); } catch (error) { if (error instanceof ResponseError) { console.error('API error:', error.message); console.error('Status code:', error.code); } else { console.error('Unexpected error:', error); } }

With Transaction

const txn = await db.beginTransaction(); try { // API calls within transaction const api = txn.api(); const user = await api.post('/users', userData); const profile = await api.post('/profiles', { userId: user.id, ...profileData }); await txn.commit(); } catch (error) { await txn.cancel(); throw error; }

Best Practices

1. Define API Types

Always define types for your API paths for better developer experience:

// Good: Type-safe type MyApi = { "/users": { get: [void, User[]] }; }; const api = db.api<MyApi>(); // Avoid: Untyped const api = db.api();

2. Reuse API Instances

Create and reuse API instances rather than creating new ones for each call:

// Good: Reuse instance const api = db.api(); await api.get('/users'); await api.get('/posts'); // Avoid: Creating multiple instances await db.api().get('/users'); await db.api().get('/posts');

3. Use Prefixes for Namespacing

Use path prefixes to organize related endpoints:

const usersApi = db.api("/users"); const postsApi = db.api("/posts"); await usersApi.get("/123"); // GET /users/123 await postsApi.get("/456"); // GET /posts/456

See Also