In most cases, we recommend using our TypeScript SDK. It leverages modern, convenient programming techniques and, being TypeScript, provides the added benefit of static type-checking for improved reliability and development efficiency.
However, a JavaScript version is also available and actively maintained. Its primary advantage is that it works directly in browsers without requiring a compiler toolchain, making it a lightweight and straightforward option for certain use cases.
To use the JavaScript SDK with npm, you can install it with the following command:
npm i merchi_sdk_js
Alternatively, the latest minified version is available at:
https://merchi.co/static/js/dist/merchi.js
You can download it for your project or hotlink it directly.
For the unminified source code and additional resources, visit the GitHub repository:
https://github.com/merchisdk/merchi_sdk_js
To include the SDK via a <script>
tag:
<script type="text/javascript" src="https://merchi.co/static/js/dist/merchi.
To access any API endpoints, authentication is required.
You can generate your API key in your developer dashboard. This key will serve as your unique identifier when making API requests.
Add the generated API key to all requests as a GET parameter. Ensure it is included in the query string for every API call.
Important: Nothing will function unless you include a valid API key in your request. Make sure to keep your key secure and avoid sharing it publicly.
All functionality in the SDK is encapsulated in a Merchi
object, which must be manually initialized. This design ensures proper namespacing. The examples in this document assume that you have already set up the merchi
object as demonstrated below:
Example: Initializing the Merchi Object
import { merchi as sdk_merchi } from "merchi_sdk_js";
// Initialize with backend and websocket URIs
const merchi = sdk_merchi("https://api.merchi.co/", "https://websockets.merchi.co/");
This setup prepares the merchi
object for use in subsequent API calls.
In the JavaScript SDK, entities utilize a fluent API style, distinguishing them from the TypeScript SDK.
Example: Getting and Setting Attributes
// getting and setting
const domain = new merchi.Domain();
console.log("Domain name is: ", domain.domain());
const name = "new-value.example.com";
const newDomain = domain.domain(name);
console.log("Domain name has now been set to: ", domain.domain());
// example of chaining multiple sets and a single get into one line
const logoUrl = domain
.domain("even-newer-value.example.com")
.smsName("sms.example.com")
.enableSmsNotifications(true)
.enableEmailNotifications(false)
.logoUrl();
console.log("Sms notifications was set to: ", domain.enableSmsNotifications());
console.log("Email notifications was set to: ", domain.enableEmailNotifications());
console.log("New domain name is: ", domain.domain());
You can retrieve a list of entities by calling the get
method on the entity name. The entity name should be in camelCase format (e.g., products
, categories
).
onSuccess
and onError
callbacks to handle the results or errors.Here’s an example demonstrating how to list products and invoices:
Example: Listing Products
// Success callback
function onSuccess(products) {
console.log("Successfully fetched products!");
console.log("Number of products:", products.length);
if (products.length > 0) {
console.log("ID of the first product:", products[0].id());
} else {
console.log("No products found.");
}
}
// Error callback
function onError(error) {
console.error("Error fetching products:", error);
}
// Optional parameters for the request
const parameters = {};
// Fetch the list of products
merchi.products.get(onSuccess, onError, parameters);
Example: Listing Invoices
// Success callback
function onSuccess(invoices) {
console.log("Successfully fetched invoices!");
console.log("Number of invoices:", invoices.length);
if (invoices.length > 0) {
console.log("ID of the first invoices:", invoices[0].id());
} else {
console.log("No invoices found.");
}
}
// Error callback
function onError(error) {
console.error("Error fetching products:", error);
}
// Optional parameters for the request
const parameters = {};
// Fetch the list of invoices
merchi.invoices.get(onSuccess, onError, parameters);
Fetching a single entity in the JavaScript SDK follows a different approach compared to the TypeScript SDK.
Here’s how it works:
Product
, Category
).get
: Use the get
method with success and error callbacks. The entity object will be automatically populated with data from the server upon success.Example: Fetching a Job
// Create a job instance
const job = new merchi.Job();
// Set the ID of the job you want to fetch
job.id(42);
// Success callback
function onSuccess() {
// `job` is now updated with data from the Merchi server
console.log(`Job type: ${job.jobType()}`);
}
// Error callback
function onError(error) {
console.error("Error fetching job:", error);
}
// Optional embed parameters for nested data
const embed = {};
// Fetch the job from the server
job.get(onSuccess, onError, embed);
Example: Fetching a Product
// Create a product instance
const product = new merchi.Product();
// Set the ID of the product you want to fetch
product.id(42);
// Success callback
function onSuccess() {
// `product` is now updated with data from the Merchi server
console.log(`Product name: ${product.name()}`);
}
// Error callback
function onError(error) {
console.error("Error fetching product:", error);
}
// Optional embed parameters for nested data
const embedProduct = {};
// Fetch the product from the server
product.get(onSuccess, onError, embedProduct);
new merchi.EntityName()
.id
of the entity using .id(value)
.onSuccess
: Called when the data is successfully fetched. The original object (product
in this example) is updated with the fetched data.onError
: Handles any errors that occur during the request.embed
parameter to include related data in the response.This method gives you fine-grained control over fetching single entities while ensuring that the object is updated in place.Creating a New Entity
As with fetching, to create a new entity on the server, you must first create a new entity object locally in javascript. Instead of filling in the objects id
, you should fill in the data that you want to provide to the new object, and then call create
. Like the other method in the javascript SDK, create
takes onSuccess
and onError
callbacks to let you know when the operation has completed.
The Merchi JavaScript SDK allows you to interact with the server to create new entities. This guide walks you through the process of creating a session and a product on the server.
To create a new entity, follow these steps:
Product
).id
.create
method to send the entity data to the server.onSuccess
and onError
callbacks to handle the operation’s result.Example: Creating a Product
Step 1: Establish a Session
Before creating any entity, you need to establish a session with the server. Use your credentials securely (ideally on the server side, not in client-side code).
const embed = {}; // Configuration object
const userName = "userName@gmail.com"; // Replace with your username
const password = "userpassword"; // Replace with your password
const newSession = new merchi.Session();
function sessionCreateSuccess() {
console.log("Session created successfully!");
}
function sessionCreateError(error) {
console.log("Error creating session: ", error);
}
// Create a session
await newSession.create(sessionCreateSuccess, sessionCreateError, embed, userName, password);
Step 2: Create a New Product
After establishing a session, you can create a product by setting its properties and calling the create
method.
const newProduct = new merchi.Product();
newProduct.name("Beans"); // Set the product name
newProduct.description("Beans are a delicious legume."); // Set the product description
function onSuccess() {
console.log(`The product has been created with id ${newProduct.id()}`);
}
function onError(error) {
console.log("Error creating product: ", error);
}
// Send the product data to the server
await newProduct.create(onSuccess, onError, embed, domainId);
userName
and password
in client-side code. Use secure server-side mechanisms for handling credentials.await
to ensure that the operations complete before proceeding..then()
and .catch()
.onError
callback to handle potential issues, such as network errors or server-side validation failures.The process for editing values on the server follows a straightforward pattern. The method used for this operation is patch
, named after the HTTP method it employs. Here’s how to edit a product:
id
(primary key) and any attributes you want to modify.patch
method to submit the changes.As with other methods, patch
accepts two callback functions: one to handle success and another to handle errors.
Example: Editing a Product
const existingProduct = new merchi.Product();
existingProduct.id(42); // we want to edit the product with id 42
existingProduct.name("New Product Name"); // we want to change its name to a ne
function onSuccess() {
console.log("The product has been edited.");
}
function onError(error) {
console.log("Error details: ", error);
}
existingProduct.patch(onSuccess, onError); // this call makes the network request
To delete an entity from the server, follow these simple steps:
id
to identify the item you want to remove.destroy
method to delete the entity.The destroy
method accepts two optional callback functions:
onSuccess
: Executes when the entity is successfully deleted.onError
: Handles and logs any errors that occur during the deletion process.Example: Deleting a Product
const existingProduct = new merchi.Product();
existingProduct.id(42); // we want to delete the product with id 42
function onSuccess() {
console.log("The product has been deleted.");
}
function onError(error) {
console.log("Error details: ", error);
}
existingProduct.destroy(onSuccess, onError);
As with the typescript SDK, nested entities can be created at once. For example, you might create a product and its category in the same request.
Example: Creating a product and category at once
const newProduct = new merchi.Product();
newProduct.name("lime");
newProduct.description("limes are green");
const newCategory = new merchi.Category();
newCategory.name("fruits");
// note that an array is provided as products may be in
// multiple categories.
newProduct.categories([newCategory]);
function onSuccess() {
console.log("the product and category both now exist");
}
const onError = console.error.bind(console);
newProduct.create(onSuccess, onError); // this call makes the network request
When working with large datasets (e.g., tens or hundreds of thousands of entities), it is not feasible to fetch all the results at once. Instead, results are returned in “pages,” allowing for efficient data retrieval and handling.
limit
Option:
offset
Option:
limit
is set to 10 and offset
is 20, the third “page” of results will be returned.Meta Information:
The result array returned to the success callback includes a
meta
object with the following details:
meta.available
: Total number of results available in the dataset.meta.count
: Number of results in the current “page.”meta.limit
: Number of results requested per page (via the limit
option).meta.offset
: Starting point for the current set of results (via the offset
option).Example: Fetching Paginated Results
function onSuccess(products) {
console.log(`Got ${products.length} products`);
console.log(`${products.meta.available} products are available`);
console.assert(products.length == products.meta.count);
console.assert(products.meta.limit == 2);
console.assert(products.meta.offset == 3);
}
function onError(error) {
console.log("Error fetching products: ", error);
}
const parameters = { offset: 3, limit: 2 };
merchi.products.get(onSuccess, onError, parameters);
Many entities in the system support a q
parameter in their list
method. This allows you to filter results by search terms, enabling quick and efficient searches.
q
parameter performs a text-based search across multiple fields."egg"
might return products with:
Example: Searching for Egg-Related Products
function onSuccess(products) {
console.log(`Got ${products.length} products`);
console.log("Product names:");
for (const product of products) {
console.log(product.name());
}
}
function onError(error) {
console.log("Error fetching products: ", error);
}
// Define search parameters with the query term
const parameters = { q: "egg" };
merchi.products.get(onSuccess, onError, parameters);
In the Merchi SDK, entities can be nested deeply and may include cyclic references. By default, the fetching and listing methods only retrieve scalar properties (e.g., strings, numbers, dates). Nested entities are not included in the response unless explicitly requested.
To include nested entities, you can use the embed
parameter to specify which nested entities to fetch and to what depth.
embed
Parameter:
embed
parameter allows you to fetch specific nested entities.embed
configuration.undefined
vs. null
:
undefined
: Indicates the nested property has not been included in the fetched data or updated locally.null
: Indicates the nested property exists but has no value on the server.Example: Fetching Nested Entities
function onSuccess(categories) {
console.log(`Got ${categories.length} categories`);
const category = categories[0];
const categoryId = category.id();
console.log(`Category name: ${category.name()}`);
console.log(`Category id: ${categoryId}`);
console.log(`Category domain: ${category.domain()}`);
}
function onError(error) {
console.log("Error fetching category: ", error);
}
const embed = { domain: {} };
merchi.categories.get(onSuccess, onError, embed);
The Merchi SDK provides advanced filtering options to narrow down results based on specific criteria. These filters are more targeted than basic search functionality, enabling precise control over the data retrieved.
inDomain
: Restricts results to a specific domain.tags
: Filters results to include only entities with specific tags.Example: Filtering Products by Tags
function onSuccess(products) {
console.log("Ok, got some products!");
console.log("Products amounts: ", products.length);
console.log("Id of the first product: ", products[0].id());
}
function onError(error) {
console.log("Error fetching products: ", error);
}
const parameters = { inDomain: 206 };
merchi.products.get(onSuccess, onError, parameters);
The Job
entity is a core object in this system, designed to manage job-related data and operations. It includes methods for creating, retrieving, updating, and interacting with job details.
import { merchi as sdk_merchi } from "merchi_sdk_js";
// Initialize with backend and websocket URIs
const merchi = sdk_merchi("https://api.merchi.co/", "https://websockets.merchi.co/");
const job = new merchi.Job();
id
: Unique identifier for the job (auto-generated).currency
: Currency used for job transactions.quantity
: Quantity associated with the job.notes
: Additional notes or comments.priority
: Priority level of the job.See the full list of properties in the source code.
create(success, error, embed, asDomain, withRights)
Creates a new job with serialized data and specified settings.
Parameters:
success
: Callback on success.error
: Callback on error.embed
: The specific nested entities that you want to fetch.asDomain
: The domain to associate with the job.withRights
: Include permissions in the request.Example:
const domainId = 42;
await job.create(
(createdJob) => console.log('Job created:', createdJob),
(err) => console.error('Error creating job:', err),
{},
domainId,
true
);
get(success, error, embed, includeArchived, withRights)
Retrieves job details by id
.
Parameters:
success
: Callback on success.error
: Callback on error.embed
: The specific nested entities that you want to fetch.includeArchived
: Include archived jobs if true
.withRights
: Include permissions in the request.Example:
job.id(12345);
await job.get(
(retrievedJob) => console.log('Job details:', retrievedJob),
(err) => console.error('Error fetching job:', err),
{},
false,
true
);
patch(success, error, embed, asDomain, withRights)
Updates job details with modified data.
Parameters:
success
: Callback on success.error
: Callback on error.embed
: The specific nested entities that you want to fetch.asDomain
: The domain to associate with the job.withRights
: Include permissions in the request.Example:
const domainId = 42;
job.notes('Updated job notes.');
await job.patch(
(updatedJob) => console.log('Job updated:', updatedJob),
(err) => console.error('Error updating job:', err),
{},
domainId,
true
);
destroy(success, error)
Deletes the job by id
.
Example:
job.destroy(
() => console.log('Job deleted successfully'),
(err) => console.error('Error deleting job:', err)
);
isComplete()
Determines if the job is complete based on its production, drafting, payment, and shipping statuses.
Example:
const isComplete = job.isComplete();
console.log('Is the job complete?', isComplete);
productTotalCost()
Calculates the total cost of the job’s product based on quantity and cost per unit.
Example:
const totalCost = job.productTotalCost();
console.log('Total product cost:', totalCost);
assignmentsUnarchived()
Returns all active (non-archived) assignments.
Example:
const activeAssignments = job.assignmentsUnarchived();
console.log('Active assignments:', activeAssignments);
hasVariations()
Checks if the job has variations.
Example:
const hasVariations = job.hasVariations();
console.log('Job has variations:', hasVariations);
variationsTotalCost()
Calculates the total cost of all variations.
Example:
const totalVariationCost = job.variationsTotalCost();
console.log('Total variations cost:', totalVariationCost);
fetchAndUpdateAssignmentById(success, error, assignmentId, embed)
Fetches the latest assignment details by ID and updates it in the job.
Example:
job.fetchAndUpdateAssignmentById(
() => console.log('Assignment updated successfully'),
(err) => console.error('Error updating assignment:', err),
123,
{}
);
So far, we’ve worked with products, categories, and job but the Merchi SDK offers many other entities such as cart, invoice, and payment. These entities help manage different parts of your store, like cart info, order details, and payment status.
For a complete list of available entities, check out the API Reference.
The TypeScript SDK is the most actively used and maintained within our development ecosystem. As a result, it may receive updates and new features more frequently compared to the JavaScript SDKs.
That said, all SDKs are fully supported and designed to meet your development needs. If you encounter any missing features or functionality in the JavaScript SDKs, please do not hesitate to contact us. We are committed to ensuring a seamless experience and can typically address such gaps or add features promptly.