ApiPromise<Req, Res, V, J>The ApiPromise class provides an interface for executing user-defined API endpoint calls. It extends Promise, allowing you to await it directly or configure the response handling.
Returned by: Methods on SurrealApi
Source: query/api.ts
Type Parameters Req - The request body type
Res - The response body type
V - Boolean for value-only response (default: false)
J - Boolean indicating if result is JSON (default: false)
Configuration Methods .json()Configure the query to return the result as a JSON string.
Returns ApiPromise<Req, Res, V, true> - Promise returning JSON string
Example const jsonString = await db . api ( ) . get ( '/users' ) . json ( ) ; console . log ( typeof jsonString ) ; // 'string'
Append a header to the API request.
apiPromise . header ( name , value ) Parameters Parameter Type Description name stringThe header name. value stringThe header value.
Returns ApiPromise<Req, Res, V, J> - Chainable promise
Example const result = await db . api ( ) . get ( '/users' ) . header ( 'X-Custom-Header' , 'value' ) . header ( 'Authorization' , 'Bearer token' ) ;
.value()Return only the response body value, without the wrapper object.
Returns ApiPromise<Req, Res, true, J> - Promise returning only the value
Examples const response = await db . api ( ) . get ( '/users' ) ; console . log ( response . body ) ; // The actual data console . log ( response . status ) ; // HTTP status console . log ( response . headers ) ; // Response headers const users = await db . api ( ) . get ( '/users' ) . value ( ) ; console . log ( users ) ; // Direct access to user array Response Structure Default Response (without .value()) interface ApiResponse < T > { body ? : T ; headers ? : Record < string , string > ; status ? : number ; } Value Response (with .value()) // Returns Res directly instead of ApiResponse<Res> Complete Examples Basic API Calls import { Surreal } from 'surrealdb' ; const db = new Surreal ( ) ; await db . connect ( 'ws://localhost:8000' ) ; const api = db . api ( ) ; // GET request const users = await api . get ( '/users' ) . value ( ) ; // POST request const newUser = await api . post ( '/users' , { name : 'John Doe' , email : 'john@example.com' } ) . value ( ) ; // PUT request const updated = await api . put ( '/users/123' , { name : 'John Smith' } ) . value ( ) ; // DELETE request await api . delete ( '/users/123' ) . value ( ) ; With Full Response const response = await db . api ( ) . get ( '/users' ) ; console . log ( 'Status:' , response . status ) ; console . log ( 'Headers:' , response . headers ) ; console . log ( 'Body:' , response . body ) ; if ( response . status === 200 ) { console . log ( 'Success:' , response . body ) ; } const result = await db . api ( ) . post ( '/protected' , data ) . header ( 'Authorization' , `Bearer ${ token } ` ) . header ( 'X-API-Version' , '2.0' ) . value ( ) ; Type-Safe API Calls interface User { id : string ; name : string ; email : string ; } interface CreateUserRequest { name : string ; email : string ; password : string ; } type ApiPaths = { "/users" : { get : [ void , User [ ] ] ; post : [ CreateUserRequest , User ] ; } ; } ; const api = db . api < ApiPaths > ( ) ; // Type-safe calls const users : User [ ] = await api . get ( '/users' ) . value ( ) ; const newUser : User = await api . post ( '/users' , { name : 'Alice' , email : 'alice@example.com' , password : 'secure' } ) . value ( ) ; Error Handling try { const user = await db . api ( ) . get ( '/users/999' ) . value ( ) ; } catch ( error ) { if ( error instanceof UnsuccessfulApiError ) { console . error ( 'API error:' , error . response ) ; console . error ( 'Status:' , error . response . status ) ; console . error ( 'Message:' , error . response . body ) ; } } async function fetchPage ( page : number , pageSize : number ) { return db . api ( ) . get ( `/users?page= ${ page } &limit= ${ pageSize } ` ) . value ( ) ; } const page1 = await fetchPage ( 1 , 20 ) ; const page2 = await fetchPage ( 2 , 20 ) ; File Upload const formData = new FormData ( ) ; formData . append ( 'file' , fileBlob ) ; formData . append ( 'name' , 'profile-picture' ) ; const result = await db . api ( ) . post ( '/upload' , formData ) . header ( 'Content-Type' , 'multipart/form-data' ) . value ( ) ; Authentication Flow // Login const loginResult = await db . api ( ) . post ( '/auth/login' , { email : 'user@example.com' , password : 'password123' } ) . value ( ) ; const { access_token } = loginResult ; // Use token for subsequent requests const api = db . api ( ) ; api . header ( 'Authorization' , `Bearer ${ access_token } ` ) ; const profile = await api . get ( '/profile' ) . value ( ) ; const orders = await api . get ( '/orders' ) . value ( ) ; Conditional Requests const api = db . api ( ) ; // Check if resource exists const checkResponse = await api . get ( '/users/123' ) ; if ( checkResponse . status === 404 ) { // Create if doesn't exist await api . post ( '/users/123' , userData ) . value ( ) ; } else { // Update if exists await api . put ( '/users/123' , userData ) . value ( ) ; } Batch Operations const api = db . api ( ) ; const promises = userIds . map ( id => api . get ( `/users/ ${ id } ` ) . value ( ) ) ; const users = await Promise . all ( promises ) ; console . log ( `Fetched ${ users . length } users` ) ; const response = await db . api ( ) . get ( '/users' ) ; const transformed = { data : response . body , timestamp : new Date ( ) , status : response . status , cached : response . headers ?. [ 'X-Cache' ] === 'HIT' } ; Retry Pattern async function apiWithRetry ( apiCall : ( ) => Promise < any > , maxRetries = 3 ) { for ( let i = 0 ; i < maxRetries ; i ++ ) { try { return await apiCall ( ) ; } catch ( error ) { if ( i === maxRetries - 1 ) throw error ; await new Promise ( r => setTimeout ( r , 1000 * ( i + 1 ) ) ) ; } } } const result = await apiWithRetry ( ( ) => db . api ( ) . get ( '/unstable-endpoint' ) . value ( ) ) ; Query Parameters // Build query params manually const params = new URLSearchParams ( { filter : 'active' , sort : 'created_at' , order : 'desc' } ) ; const users = await db . api ( ) . get ( `/users? ${ params } ` ) . value ( ) ; WebSocket vs API Endpoints // Both use the same connection const db = new Surreal ( ) ; await db . connect ( 'ws://localhost:8000' ) ; // Regular query (via WebSocket/HTTP RPC) const users1 = await db . select ( new Table ( 'users' ) ) ; // API endpoint (via defined API routes) const users2 = await db . api ( ) . get ( '/users' ) . value ( ) ; // Both work, but API endpoints allow custom logic const response = await db . api ( ) . get ( '/users' ) ; console . log ( 'Content-Type:' , response . headers ?. [ 'Content-Type' ] ) ; console . log ( 'Cache-Control:' , response . headers ?. [ 'Cache-Control' ] ) ; console . log ( 'X-Custom:' , response . headers ?. [ 'X-Custom-Header' ] ) ; Best Practices 1. Use Type Definitions // Good: Type-safe API type MyApi = { "/users" : { get : [ void , User [ ] ] } ; } ; const api = db . api < MyApi > ( ) ; // Avoid: Untyped const api = db . api ( ) ; 2. Use .value() for Simpler Code // Good: Direct value access const users = await api . get ( '/users' ) . value ( ) ; // More verbose: const response = await api . get ( '/users' ) ; const users = response . body ; 3. Handle Errors Gracefully // Good: Specific error handling try { const result = await api . get ( '/users' ) . value ( ) ; } catch ( error ) { if ( error instanceof UnsuccessfulApiError ) { // Handle API errors } } See Also