InstantDB API
The InstantDB
class is the main entry point for interacting with your InstantDB database. It provides methods for initialization, queries, transactions, authentication, and real-time synchronization.
Initialization
InstantDB.init()
Initialize a new InstantDB instance.
static Future<InstantDB> init({ required String appId, InstantConfig config = const InstantConfig(),})
Parameters:
appId
(String
): Your InstantDB application IDconfig
(InstantConfig
, optional): Configuration options
Returns: Future<InstantDB>
- The initialized database instance
Example:
final db = await InstantDB.init( appId: 'your-app-id', config: const InstantConfig( syncEnabled: true, verboseLogging: false, ),);
InstantConfig
Configuration options for InstantDB initialization.
class InstantConfig { const InstantConfig({ this.syncEnabled = true, this.verboseLogging = false, this.apiUrl = 'https://api.instantdb.com', this.websocketUrl = 'wss://api.instantdb.com/ws', });
final bool syncEnabled; final bool verboseLogging; final String apiUrl; final String websocketUrl;}
Properties:
syncEnabled
(bool
): Enable real-time synchronization (default:true
)verboseLogging
(bool
): Enable detailed debug logging (default:false
)apiUrl
(String
): Custom API endpoint URLwebsocketUrl
(String
): Custom WebSocket endpoint URL
Core Properties
appId
Get the application ID for this database instance.
String get appId
Returns: String
- The application ID
Example:
print('Database app ID: ${db.appId}');
auth
Access the authentication manager.
AuthManager get auth
Returns: AuthManager
- The authentication manager instance
Example:
final currentUser = db.auth.currentUser.value;if (currentUser != null) { print('User: ${currentUser.email}');}
presence
Access the presence manager for real-time collaboration.
PresenceManager get presence
Returns: PresenceManager
- The presence manager instance
Example:
final room = db.presence.joinRoom('chat-room');await room.setPresence({'status': 'online'});
syncEngine
Access the synchronization engine (nullable).
SyncEngine? get syncEngine
Returns: SyncEngine?
- The sync engine instance, null if sync is disabled
Example:
final isConnected = db.syncEngine?.connectionStatus.value ?? false;print('Connected: $isConnected');
Query Methods
subscribeQuery()
Create a reactive query that updates automatically when data changes.
Signal<QueryResult> subscribeQuery(Map<String, dynamic> query)
Parameters:
query
(Map<String, dynamic>
): The InstaQL query object
Returns: Signal<QueryResult>
- A reactive signal containing query results
Example:
final todosSignal = db.subscribeQuery({ 'todos': { 'where': {'completed': false}, 'orderBy': {'createdAt': 'desc'}, 'limit': 20, },});
// Use in reactive widgetsWatch((context) { final result = todosSignal.value; final todos = result.data?['todos'] ?? []; return TodoList(todos: todos);});
queryOnce()
Execute a one-time query without creating a subscription.
Future<QueryResult> queryOnce(Map<String, dynamic> query)
Parameters:
query
(Map<String, dynamic>
): The InstaQL query object
Returns: Future<QueryResult>
- The query result
Example:
final result = await db.queryOnce({ 'users': { 'where': {'role': 'admin'}, 'limit': 5, },});
final adminUsers = result.data?['users'] ?? [];print('Found ${adminUsers.length} admin users');
Transaction Methods
transact()
Execute a transaction with a list of operations or transaction chunk.
Future<TransactionResult> transact(dynamic transaction)
Parameters:
transaction
(List<Operation>
orTransactionChunk
): The operations to execute
Returns: Future<TransactionResult>
- The transaction result
Example:
// With list of operationsawait db.transact([ ...db.create('todos', { 'id': db.id(), 'text': 'Learn InstantDB', 'completed': false, }),]);
// With transaction chunk (new tx API)await db.transact( db.tx['todos'][todoId].update({'completed': true}));
transactChunk()
(Deprecated)
Execute a transaction chunk. Use transact()
instead.
@Deprecated('Use transact() instead')Future<TransactionResult> transactChunk(TransactionChunk chunk)
create()
Create a new entity operation.
List<Operation> create(String entityType, Map<String, dynamic> data)
Parameters:
entityType
(String
): The type of entity to createdata
(Map<String, dynamic>
): The entity data
Returns: List<Operation>
- List containing the create operation
Example:
final operations = db.create('posts', { 'id': db.id(), 'title': 'Hello World', 'content': 'This is my first post', 'authorId': userId, 'createdAt': DateTime.now().millisecondsSinceEpoch,});
await db.transact(operations);
update()
Create an update entity operation.
Operation update(String entityId, Map<String, dynamic> data)
Parameters:
entityId
(String
): The ID of the entity to updatedata
(Map<String, dynamic>
): The data to update
Returns: Operation
- The update operation
Example:
await db.transact([ db.update(postId, { 'title': 'Updated Title', 'updatedAt': DateTime.now().millisecondsSinceEpoch, }),]);
delete()
Create a delete entity operation.
Operation delete(String entityId)
Parameters:
entityId
(String
): The ID of the entity to delete
Returns: Operation
- The delete operation
Example:
await db.transact([ db.delete(postId),]);
merge()
Create a deep merge operation.
Operation merge(String entityId, Map<String, dynamic> data)
Parameters:
entityId
(String
): The ID of the entity to mergedata
(Map<String, dynamic>
): The data to deep merge
Returns: Operation
- The merge operation
Example:
await db.transact([ db.merge(userId, { 'preferences': { 'theme': 'dark', 'notifications': {'email': false}, }, }),]);
link()
Create a link operation between entities.
Operation link(String fromId, String linkName, String toId)
Parameters:
fromId
(String
): The source entity IDlinkName
(String
): The name of the link relationshiptoId
(String
): The target entity ID
Returns: Operation
- The link operation
Example:
await db.transact([ db.link(userId, 'posts', postId),]);
unlink()
Create an unlink operation between entities.
Operation unlink(String fromId, String linkName, String toId)
Parameters:
fromId
(String
): The source entity IDlinkName
(String
): The name of the link relationshiptoId
(String
): The target entity ID
Returns: Operation
- The unlink operation
Example:
await db.transact([ db.unlink(userId, 'posts', postId),]);
Transaction API (tx namespace)
tx
Access the new transaction API namespace for fluent operations.
TransactionNamespace get tx
Returns: TransactionNamespace
- The transaction namespace
Example:
// Fluent API for complex operationsawait db.transact( db.tx['users'][userId] .update({'name': 'New Name'}) .link({'posts': [postId]}) .merge({ 'preferences': {'theme': 'dark'}, }));
Utility Methods
id()
Generate a new UUID for entity IDs.
String id()
Returns: String
- A new UUID string
Example:
final newId = db.id();print('Generated ID: $newId'); // e.g., "123e4567-e89b-12d3-a456-426614174000"
await db.transact([ ...db.create('items', { 'id': newId, 'name': 'New Item', }),]);
lookup()
Create a lookup reference for referencing entities by attribute instead of ID.
LookupRef lookup(String entityType, String attribute, dynamic value)
Parameters:
entityType
(String
): The type of entity to lookupattribute
(String
): The attribute to match againstvalue
(dynamic
): The value to match
Returns: LookupRef
- A lookup reference object
Example:
// Reference user by email instead of IDawait db.transact([ ...db.create('posts', { 'id': db.id(), 'title': 'Hello World', 'authorId': lookup('users', 'email', 'john@example.com'), }),]);
// Use in queriesfinal posts = db.subscribeQuery({ 'posts': { 'where': { 'author': lookup('users', 'email', 'john@example.com'), }, },});
Authentication Helpers
getAuth()
Get the current authentication state (one-time check).
AuthUser? getAuth()
Returns: AuthUser?
- The current user, or null if not authenticated
Example:
final currentUser = db.getAuth();if (currentUser != null) { print('Logged in as: ${currentUser.email}');} else { print('Not logged in');}
subscribeAuth()
Get a reactive signal for authentication state changes.
Signal<AuthUser?> subscribeAuth()
Returns: Signal<AuthUser?>
- A reactive signal for auth state
Example:
Watch((context) { final user = db.subscribeAuth().value; return user != null ? Text('Welcome, ${user.email}') : Text('Please sign in');});
getAnonymousUserId()
Get or generate an anonymous user ID for presence and collaboration.
String getAnonymousUserId()
Returns: String
- An anonymous user ID
Example:
final anonymousId = db.getAnonymousUserId();final room = db.presence.joinRoom('public-room', initialPresence: { 'userId': anonymousId, 'userName': 'Guest ${anonymousId.substring(0, 4)}',});
Lifecycle Methods
dispose()
Clean up database resources and connections.
Future<void> dispose()
Returns: Future<void>
Example:
@overridevoid dispose() { super.dispose(); // Clean up database when app is disposed db.dispose();}
Error Handling
All InstantDB methods can throw InstantException
for database-related errors:
try { await db.transact([ ...db.create('invalid', {}), // Missing required fields ]);} on InstantException catch (e) { print('InstantDB Error: ${e.code}'); print('Message: ${e.message}');
// Handle specific error types switch (e.code) { case 'validation_error': // Handle validation errors break; case 'network_error': // Handle network issues break; case 'auth_error': // Handle authentication errors break; }} catch (e) { print('Unexpected error: $e');}
Complete Example
Here’s a complete example showing common InstantDB operations:
class TodoService { final InstantDB db;
TodoService(this.db);
// Get reactive todos Signal<QueryResult> getTodos({bool? completed}) { return db.subscribeQuery({ 'todos': { if (completed != null) 'where': {'completed': completed}, 'orderBy': {'createdAt': 'desc'}, }, }); }
// Create a new todo Future<void> createTodo({ required String text, bool completed = false, }) async { await db.transact([ ...db.create('todos', { 'id': db.id(), 'text': text, 'completed': completed, 'createdAt': DateTime.now().millisecondsSinceEpoch, 'userId': db.auth.currentUser.value?.id, }), ]); }
// Update todo using new tx API Future<void> updateTodo(String todoId, {String? text, bool? completed}) async { final updates = <String, dynamic>{}; if (text != null) updates['text'] = text; if (completed != null) updates['completed'] = completed; updates['updatedAt'] = DateTime.now().millisecondsSinceEpoch;
await db.transact( db.tx['todos'][todoId].update(updates) ); }
// Delete todo Future<void> deleteTodo(String todoId) async { await db.transact([db.delete(todoId)]); }
// Get todos by user email (using lookup) Signal<QueryResult> getTodosByUser(String email) { return db.subscribeQuery({ 'todos': { 'where': { 'user': lookup('users', 'email', email), }, }, }); }
// Bulk operations Future<void> markAllCompleted() async { final result = await db.queryOnce({ 'todos': {'where': {'completed': false}}, });
final todos = (result.data?['todos'] as List? ?? []) .cast<Map<String, dynamic>>();
final operations = todos.map((todo) => db.update(todo['id'], {'completed': true}) ).toList();
if (operations.isNotEmpty) { await db.transact(operations); } }}
Next Steps
Explore specific API areas:
- Transactions API - Detailed transaction and operation methods
- Queries API - Advanced querying and InstaQL syntax
- Presence API - Real-time collaboration methods
- Flutter Widgets - Reactive UI components
- Types Reference - Complete type definitions