Skip to main content

Data model

Qoyod organizes its data around five entities that every inventory integration will encounter: Product, Inventory location, Account, Invoice, and Contact. Understanding what Qoyod considers each entity to be -- and which fields identify it -- is the prerequisite for mapping your integrated system's records correctly. This page does not cover sync directions or conflict handling; those are addressed in sync directions.

Core entities

The table below names each entity, the Qoyod API tag that exposes it, and the fields most relevant to integration work. Full field details are in the Qoyod API reference.

EntityQoyod API tagKey fieldsNotes
Productproductsid, name_en, name_ar, sku, type, track_quantitytype enum controls record classification
Inventory locationinventoriesid, name, ar_name, is_default, account_idOne record per physical or logical warehouse
Accountaccountsid, code, name_en, name_ar, account_kind, parent_kind, branch_kindLeaf nodes in the chart of accounts hierarchy
Invoiceinvoices id Formal request for payment from a customer
Contactcontacts id Represents a Customer or Vendor

Product is the central entity for inventory integrations. Each product record has a type field that classifies it as one of: Product, Service, Expense, RawMaterial, or Recipe. This classification determines how Qoyod treats the record in accounting and inventory contexts -- for example, only records with track_quantity set to 1 have their stock levels managed across inventory locations.

Inventory location represents a physical or logical place where stock is held. Each location has a unique Qoyod ID. When a product has track_quantity enabled, its stock level is tracked per inventory location. The is_default field identifies the location Qoyod uses when no explicit location is specified.

Account is a leaf node in Qoyod's chart of accounts. Accounts are organized in a three-level hierarchy: main account (identified by parent_kind) -> branch account (identified by branch_kind) -> sub-account (identified by account_kind). Products reference accounts via sales_account_id and expense_account_id, which connect product transactions to the correct ledger entries.

Invoice is a commercial document that records a formal request for payment from a Customer for goods or services delivered. Every invoice Qoyod creates generates corresponding debit and credit entries in the general ledger automatically.

Contact is the party record that represents either a Customer (a party that purchases from the merchant) or a Vendor (a party the merchant purchases from). Invoices and bills reference a Contact as the counterparty to the transaction.

How entities relate

The five entities connect to each other in ways that affect how data must be structured when you synchronize between your integrated system and Qoyod.

A Product belongs to a Category (via category_id). When a product has track_quantity set to 1, its current stock levels appear nested within the product record under inventories -- one entry per inventory location, each with a stock value.

An Inventory location holds the stock of Products. The relationship is many-to-many: each product can have stock across multiple locations, and each location can hold many products. Qoyod populates this relationship when stock-affecting transactions occur; the integrator does not manage it directly.

An Invoice references one or more Products as line items and exactly one Contact as the counterparty. When Qoyod records an invoice, it decrements stock for tracked products in the relevant inventory location and posts entries to the accounts linked to those products.

An Account sits at the leaf of the chart of accounts hierarchy. Products reference specific accounts for sales and cost-of-goods-sold entries. Inventory locations reference an account via account_id for inventory-related transactions.

Mapping your data to Qoyod

When you build an integration, your task is to decide which records in your integrated system correspond to which Qoyod entities, and which fields carry the correspondence.

Identifying records across systems

Qoyod assigns every entity a numeric id when the record is created. Your integration should store this Qoyod ID on the corresponding record in your integrated system so that future updates can target the correct Qoyod record without a lookup.

The product type enum

The type field on a product record determines its classification in Qoyod. The five values are:

ValueMeaning
ProductA physical good that can be bought and sold. Default when type is omitted on creation.
ServiceAn intangible offering that can be sold but does not have stock.
ExpenseA cost item that is not sold to customers.
RawMaterialA component used as input in a Recipe.
RecipeA compound product assembled from RawMaterial ingredients.

When mapping your integrated system's product catalog to Qoyod, assign type based on what the record represents. A digital download is a Service. A bundle composed of components may be a Recipe. The type field is set on creation and ignored on update, so the classification must be correct from the first synchronization.

Required fields by entity

  • Product: The product wrapper object is required. Send at minimum name_en or name_ar and a type value to produce a meaningful record.
  • Inventory location: name is required. All other fields are optional.
  • Account: en_name, ar_name, account_kind, parent_kind, and branch_kind are required. code is auto-generated if omitted.

Tracking Qoyod stock levels

To read current stock levels from Qoyod, retrieve a product record. The inventories array in the product response includes one entry per inventory location, with the current stock value at that location. Stock levels change in Qoyod when invoices, bills, inventory transfers, or stock takes are recorded -- they are not written directly by the integration.

  • Sync directions -- which system initiates data flow and what each direction requires.
  • Pagination and filtering -- how to page through large entity lists when polling Qoyod.
  • Qoyod API reference -- full field-level documentation for all entities.