SurrealApiThe 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
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[]
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");
PathDefDefines 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] | [];
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 }]; }; };
.header()Configure a header for all requests sent by this API instance. Useful for setting common headers like authentication tokens or content types.
Method Syntaxapi.header(name, value)
| Parameter | Type | Description |
|---|---|---|
name required | string | The name of the header to configure. |
value required | string | null | The value to set, or null to remove the header. |
void
Set Custom Headerapi.header('X-API-Key', 'my-secret-key');
Remove Headerapi.header('X-API-Key', null);
Set Authorization Headerapi.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.
TipPrefer using method-specific functions (
.get(),.post(), etc.) for better type safety.
Method Syntaxapi.invoke<Req, Res>(path, request?)
| Parameter | Type | Description |
|---|---|---|
path required | string | The API path to invoke. |
request optional | ApiRequest<Req> | The request configuration object. |
ApiPromise<Req, Res> - A promise for the API response
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 Syntaxapi.get(path)
| Parameter | Type | Description |
|---|---|---|
path required | P extends ValidPaths<TPaths, “get”> | The API path to invoke. |
ApiPromise<void, ResponseBody> - A promise for the GET response
Get All Usersconst users = await api.get("/users");
Get Specific Userconst user = await api.get("/users/123");
.post()Invoke a user-defined POST API endpoint.
Method Syntaxapi.post(path, body?)
| Parameter | Type | Description |
|---|---|---|
path required | P extends ValidPaths<TPaths, “post”> | The API path to invoke. |
body optional | RequestBody<TPaths, P, “post”> | The request body to send. |
ApiPromise<RequestBody, ResponseBody> - A promise for the POST response
const newUser = await api.post("/users", { name: "John Doe", email: "john@example.com" });
.put()Invoke a user-defined PUT API endpoint.
Method Syntaxapi.put(path, body?)
| Parameter | Type | Description |
|---|---|---|
path required | P extends ValidPaths<TPaths, “put”> | The API path to invoke. |
body optional | RequestBody<TPaths, P, “put”> | The request body to send. |
ApiPromise<RequestBody, ResponseBody> - A promise for the PUT response
const updated = await api.put("/users/123", { name: "John Smith", email: "john.smith@example.com" });
.delete()Invoke a user-defined DELETE API endpoint.
Method Syntaxapi.delete(path, body?)
| Parameter | Type | Description |
|---|---|---|
path required | P extends ValidPaths<TPaths, “delete”> | The API path to invoke. |
body optional | RequestBody<TPaths, P, “delete”> | Optional request body. |
ApiPromise<RequestBody, ResponseBody> - A promise for the DELETE response
await api.delete("/users/123");
.patch()Invoke a user-defined PATCH API endpoint.
Method Syntaxapi.patch(path, body?)
| Parameter | Type | Description |
|---|---|---|
path required | P extends ValidPaths<TPaths, “patch”> | The API path to invoke. |
body optional | RequestBody<TPaths, P, “patch”> | The partial updates to apply. |
ApiPromise<RequestBody, ResponseBody> - A promise for the PATCH response
const updated = await api.patch("/users/123", { email: "newemail@example.com" });
.trace()Invoke a user-defined TRACE API endpoint.
Method Syntaxapi.trace(path, body?)
| Parameter | Type | Description |
|---|---|---|
path required | P extends ValidPaths<TPaths, “trace”> | The API path to invoke. |
body optional | RequestBody<TPaths, P, “trace”> | Optional request body. |
ApiPromise<RequestBody, ResponseBody> - A promise for the TRACE response
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' });
// 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" });
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);
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
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); } }
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; }
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();
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');
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