SyncHive Apps
A SyncHive App is an application that uses the SyncHive Unified Data Store (UDS) as its data store.
Apps are registered to a specific SyncHive instance. Once registered, an app can write data to and read data from SyncHive through the Unified Data Store.
Data exchange between SyncHive Apps and SyncHive occurs via APIs, using SyncHive shapes as the data contract.
Registering a New App
- Open SyncHive Apps
- Click Register App
- Enter the app details:
- Name
- Shapes it integrates with
- Status: enabled or disabled
- App URLs: the URL(s) where your app is hosted. SyncHive will only allow sign-in and API access from these URL(s).
- Confirm registration
Once saved, SyncHive will generate a publishable key for the app and display it in the connection details. You’ll use this key in your app to initialize the SyncHive Javascript SDK.
Viewing and Editing Registered Apps
The SyncHive Apps main page displays a list of all apps registered within your SyncHive instance.
For each app, you can see:
- App name
- Shapes it connects to
- Current status
From this page, you can:
- View the app’s connection details
- Edit the app’s registration information
- Change the app’s status
- Delete the app’s connection
Building Your App
SyncHive Apps are built using the official SyncHive JavaScript SDK, which handles sign-in and secure access automatically.
View the SDK on GitHub: https://github.com/synchivehq/synchive-js.
Most apps install it via npm:
npm install @synchive/synchive-js
Once installed, your app can connect to SyncHive. In the snippet below, replace the placeholder value for publishableKey with the publishable key from the app’s connection details.
import { SyncHiveClient } from "@synchive/synchive-js";
const synchive = new SyncHiveClient({
publishableKey: "sh_publishable_...",
});
// Initialize the client first.
try {
await synchive.init();
} catch (error) {
// Surface sign-in callback errors to the user.
console.error("Auth failed:", error);
}
// Listen for auth lifecycle events.
synchive.onAuthStateChange(({ user }, event) => {
// Fires immediately on mount, then whenever auth state changes.
if (event === "authenticated") {
// User is signed in. Show logged-in UI.
// setUser(user);
}
if (event === "unauthenticated") {
// User is signed out. Show logged-out UI.
// setUser(null);
}
});
// Call these from your UI event handlers:
// await synchive.signInRedirect();
// await synchive.signOutRedirect();
Quick flow:
- Create
SyncHiveClientwith your app'spublishableKey. - Call
await synchive.init()once on app startup. - React to
onAuthStateChangeevents to render signed-in vs signed-out UI. - Use
signInRedirect()andsignOutRedirect()from your UI event handlers.
Requesting Data from SyncHive
After signing in, you can access SyncHive data using simple helper methods.
List Records
Use list() to fetch records from a shape:
const products = await synchive.list("Product", {
top: 20,
});
Get a Specific Record
Use get() to retrieve a single record by its hiveId:
const product = await synchive.get("Product", "D6BFA0AB71A1");
Create a Record
Use create() to create a new record in a shape:
const createdProduct = await synchive.create("Product", {
name: "Two-Slice Toaster",
sku: "TOASTER-2S-BLK",
});
create() returns the full created shape record.
Update a Record
Use update() to update an existing record by hiveId.
For update requests, the root hiveId is required in the payload.
You can pass either a partial shape or a full shape:
const updatedProduct = await synchive.update("Product", "D6BFA0AB71A1", {
hiveId: "D6BFA0AB71A1",
status: "discontinued",
});
- You can soft delete a record using
update()by setting"isDeleted"totrue. - Note:
"isDeleted"must be enabled on the shape before you can use soft deletes. update()returns the full updated shape record unless it has been soft deleted, in which case it returns nothing.- You can view soft-deleted records in SyncHive Explore by clicking Filter, then Show Deleted, and then Apply Filters.
Filtering and Paging
You can pass query options such as:
topcontrols how many records are returned (maximum500per request)skipcontrols how many records are skipped before returning resultsfilterlets you request only records that match specific conditionsorderbysorts records by one or more fields (useascordesc)
Additional details:
- If
topis greater than500, SyncHive uses500instead. - For
orderby, use a comma-separated list such ascreatedOn desc,name asc.
Example:
const salesOrders = await synchive.list("SalesOrder", {
filter:
"transactionNumber eq 'TOASTER-1001' and salesOrderItem/any(i: i/name eq '4-Slice Toaster')",
orderby: "createdOn desc,transactionNumber asc",
skip: 0,
top: 25,
});
Supported filters
SyncHive supports only this subset of the OData filter syntax:
- Comparison operators:
eq,ne,gt,lt,ge,le - Logical operators:
and,or,not - Collection operators:
any,all - One text function:
contains(field,'value')
Examples of supported filters:
status eq 'Active'status ne 'Inactive'hiveId eq 'D6BFA0AB71A1'(hiveIdfilters support only theeqoperator)amount gt 100 and amount lt 500total ge 1000 or discount le 25not (status eq 'Archived')salesOrderItem/any(i: i/name eq '4-Slice Toaster')salesOrderItem/all(i: i/quantity ge 1)contains(customerName,'Acme')
Unsupported filters
SyncHive does not currently support:
- Other OData functions such as
startswith(),endswith(),length(), ortolower() - Lambda expressions beyond
anyandall - Full OData query features such as
expandor advanced nested function combinations
Examples of unsupported filters:
startswith(customerName,'A')endswith(customerName,'Inc')hiveId ne 'D6BFA0AB71A1'length(customerName) gt 10tolower(customerName) eq 'acme'salesOrderItem/filter(i: i/qty gt 1)contains(tolower(customerName),'acme')expand=salesOrderItem
If a filter uses syntax not listed in Supported filters, treat it as unsupported.
Troubleshooting
App URLs
If your sign-in does not work, the most common cause is an App URL mismatch.
When this happens, you will see:
- "Access Denied"
- "The app has not been registered in SyncHive to use the following URL..."
This means the app URL you entered in SyncHive does not exactly match the URL your app is using during sign-in.
Common issues
- A missing or extra slash
- Entered in SyncHive:
https://my-app.com/sign-in - App is using:
https://my-app.com/sign-in/
- Entered in SyncHive:
httpvshttps- Entered in SyncHive:
https://my-app.com/sign-in - App is using:
http://my-app.com/sign-in
- Entered in SyncHive:
- Different web address
- Entered in SyncHive:
https://portal.my-app.com/sign-in - App is using:
https://my-app.com/sign-in
- Entered in SyncHive:
- Different path or capitalization
- Entered in SyncHive:
https://my-app.com/Sign-In/ - App is using:
https://my-app.com/sign-in/
- Entered in SyncHive:
How to fix
- Copy the URL provided to you on the "Access Denied" page.
- Open Apps in SyncHive and select your app.
- Paste the URL you copied on the "Access Denied" page in to one of the App URL(s) fields.
- Save your changes.
- Try signing in again.