Models are used to define and manage data structures in your application. They enable you to map your data to the underlying database and create relationships between different entities. When a model is defined and installed by a Swell App, it becomes an integral part of a store’s database schema.

Once a model is defined, Swell dynamically generates backend API endpoints, eliminating the need to manually create custom endpoints for backend services, and streamlining the process of exposing your data to the frontend or other services.

A model schema supports various field types, such as scalar values, arrays, nested objects, and links to other models, allowing you to create diverse data structures. Links help establish relationships between models, making it easier to navigate and work with related data. Scalar field types include basic data types such as strings, integers, and booleans. Arrays allow for collections of values, while nested objects enable you to create complex, hierarchical data structures.

See the Field type reference documentation for more information.

Models include built-in validation and type coercion mechanisms. The key principle is to ensure that your data is consistent without being overly rigid and hard to work with. Validation constraints include required fields, unique constraints, and custom validation rules. Automatic type coercion ensures that API input data is converted to the appropriate data type when querying and creating records.

Events can be configured to emit when a specific action occurs, such as creating, updating, or deleting a record with specific properties. Webhooks and Functions can be subscribed to these events. Triggers are model-defined actions that respond to record conditions and can be used to propagate changes to other records automatically. By using events and triggers, you can create a dynamic and responsive application that automatically reacts to changes in your data.

When working with models, you often need to fetch and consistently display data. Default query parameters allow you to define standard settings for data retrieval, such as pagination, sorting order, and the number of items to display per page.

A primary field is the main identifier for a record, used for lookup and reference purposes. The primary field should be unique and is set to id by default. A secondary field allows for a more human-readable alternative identifier, for example, a product slug.

Swell employs techniques to optimize database queries automatically, while App-specific indexes can be created on one or more fields and can include additional options, such as expiration time. By using indexes, you can significantly improve the performance of your application, especially when dealing with large amounts of data.

Model namespaces are a way to group and organize related models. They help prevent naming conflicts between different models in an app and provide a clear structure for organizing your data. Note that all App-defined models and fields are scoped to API keys and dynamically layered to prevent naming collisions across applications. Therefore, it’s not necessary to use namespaces for any purpose other than convenience and organization.

You can extend existing models to create new models with additional properties and behaviors through model inheritance. This enables you to create a hierarchy of models sharing common properties and behaviors, promoting organization and maintainability in your application. To extend a model, specify the parent model using the extends property in the model definition. Additionally, indicate the version of the parent model to inherit from with the extends_version property.

Swell offers two specialized types of models: singular and abstract. A singular model represents a single record in your application, such as a site configuration or a global setting. An abstract model serves as a base for other models to extend, but cannot be instantiated directly. Abstract models are useful for creating reusable data structures and enforcing consistent behavior across your schema.

Swell automatically tracks changes to models over time using semantic versioning. When a model is updated, the version number is incremented as a patch, although you can also specify a new major or minor version in your configuration. This helps maintain compatibility between different versions of your application without breaking existing functionality.

There are two types of model configurations representing both low-level database fields and high-level content management interfaces. To learn more about these concepts, read the Models introduction and our general guide on Data model customization.

With an understanding of how models work, you can construct app configurations that automatically introduce new models as well as new fields to standard models when installed.

A data model configuration has the ability to modify a merchant store’s own data schema in a secure, observable, and isolated manner.

Since Swell data models are dynamically instantiated as REST endpoints, any models you define will essentially enhance a merchant’s own API in what feels like a first-class, native interface. See architecture if you’re interested in how it works.

You can create a new data model via the Backend API, or by using the following CLI command:

swell create model

→ See the CLI reference for more details and options.

Here's an example of a new data model:

{
  "collection": "things",
  "label": "Things",
  "fields": {
    "name": {
      "type": "string",
      "required": true
    },
    "description": {
      "type": "string"
    }
  }
}

A model configuration can either instantiate a new collection, such as above, or append to an existing collection such as products.

Here’s an example of appending fields to an existing collection:

{
  "collection": "products",
  "fields": {
    "app_property_1": {
      "type": "string",
      "required": true
    },
    "app_property_2": {
      "type": "int"
    }
  }
}

In the above example, the resulting model will append the field definition my_app_field to the existing products model.

Notice how there is no explicit namespace on the field object. This is intentional, as Swell handles namespace conflicts in a unique way that supports overlapping fields among apps, without causing conflicts internally or externally. It works because each API key is identified by a specific app, and data is isolated by an internal structure. App models and fields can still be accessed without an app-scoped API key, however, the model API endpoint necessarily has a namespace prefix in that case. See our app introduction for more details.

Consider content models as a layer above data models, with the primary purpose of defining the content management experience presented in a store’s dashboard.

This two-tiered approach makes it easier to separate concerns between the database schema, API functionality, and administrative workflows. See our guide on content models vs data models for more details.

You can create a new content model manually, or by using the following CLI command:

swell create content

→ See the CLI reference for more details and options.

Here's an example of a new content model:

{
  "collection": "things",
  "fields": [
    {
      "id": "name",
      "type": "text"
      "required": true
    },
    {
      "id": "description",
      "type": "long_text"
      "hint": "Describe this thing in 2-3 sentences"
    }
  ]
}

Notice the difference between content and data model configurations. Content models prefer UI-oriented field types, which for example can specify short vs long text, and field ordering to display in the admin dashboard, while data models are purely schema-oriented to structure the database and related APIs.

In the above example, the things collection is not standard, therefore a new data model and collection will be established by the app. If it did exist, then the platform would automatically enhance the underlying data model associated with that collection.

All model collections are private by default, but to support accessing data from the frontend API you can declare individual fields or entire models as public, along with specific query parameters that can limit the range of fields returned using a public key.

Here’s an example model with a public field:

{
  "collection": "vendors",
  "label": "Vendors",
  "fields": {
    "name": {
      "type": "string",
      "required": true,
      "public": true
    },
    "active": {
      "type": "bool"
    },
    "description": {
      "type": "string"
    }
  },
  "public_permissions": {
    "query": {
      "active": true
    },
    "expands": {
      "products": {
        "url": "/products",
        "params": {
          "vendor_id": "id"
        },
        "data": {
          "active": true
        }
      }
    }
  }
}

With at least 1 public field declared, all records can be accessed by the frontend API, with only the public fields being returned in a response. In addition, you can limit the range of results to only include active records using public_permissions, and specify how expand parameters should be treated for the collection in a public scope.