Schema Types Overview
Learn how to use schema types to define, validate, and interact with objects in the Nextiva SDK
Summary
Schema Types define the structure, behavior, and access patterns for all domain objects, such as User, Queue, Campaign, and Contact, used by the Nextiva SDK. By standardizing these definitions, the SDK ensures consistent data handling, validation, and interaction patterns across all integrations.
This article provides a comprehensive overview of Schema Types, from the high-level architecture to the practical, hands-on implementation using the SchemaTypeClient.
What is a Schema Type?
A Schema Type is a contract that serves as a blueprint for a particular kind of data entity. It describes how an object is structured, accessed, created, updated, and deleted.
In practice, every Schema Type:
- Defines the fields and data types for its object.
- Drives CRUD operations (for example, create, retrieve, update, or delete) in the SDK.
- Determines access points for an object, like whether it can be duplicated.
- Supports validation, permissions, and versioning out of the box.
- Provides a consistent developer experience across all integrations.
Expansion: linking to other objects
An Expansion provides a way to link an ID to a full object. For example, a user object might store a user_profile_id. Through expansion, the SDK can retrieve the full user profile object using that ID.
In practice, many schema types include an expansions field in their data structure. This field contains the fully-populated objects that have been expanded from simple ID references, allowing developers to access related data without making additional API calls.
The structure of a Schema Type
All Schema Types follow a standardized format that defines their behavior and metadata.
| Section | Description |
|---|---|
| Metadata | Defines the required and optional attributes of the object. Data types are primitive (e.g., string, number, boolean) or complex (object, array). |
| Fields | Describes links to other schema types (e.g., a User’s relation to a Contact). |
| Relations | Defines accepted values, formats, and constraints for fields. |
| Validation Rules | Specifies which fields should be indexed for faster queries. |
| Indexes | Defines the available API actions or operations for the schema type. |
| Links | Tracks changes to the schema over time to ensure backward compatibility. |
| Versioning | Defines the required and optional attributes of the object. Data types are primitive (e.g., string, number, boolean) or complex (object, array). |
Links: the actions you can perform
Each schema type defines a set of links, which represent the available API actions. The SchemaTypeClient uses these links to construct and execute the appropriate requests.
Common links include:
- create: Creates a new instance of the schema type.
- retrieve: Retrieves an existing instance by its ID.
- update: Updates an existing instance.
- delete: Deletes an instance.
- search: Searches for instances based on a query.
- download: Downloads a file associated with an instance.
Using the SchemaTypeClient
The SchemaTypeClient is the primary interface for developers to interact with schema types. It abstracts the underlying API calls, offering a simple and consistent set of methods.
Initialization
The SchemaTypeClient is obtained from an instance of the NCX SDK.
import { Nextiva } from '@nextiva/ncx-web-sdk';
const sdk = new Nextiva({
// ...configuration options
});
const schemaTypeClient = sdk.getSchemaTypeClient();CRUD operations
The client provides methods for all fundamental CRUD operations.
Create
To create a new object of a schema type, use the create method. The payload must include all required fields for that schema.
// Using the 'contact' schema as an example
const newContact = await schemaTypeClient.create('contact', {
data: {
firstName: "Alex",
lastName: "Ray",
name: "Alex Ray",
connections: [
{ type: "email", value: "[email protected]", isPrimary: true }
],
tenantId: "t_abcde", // Required field
createdAt: Date.now(), // Required field (as a number)
createdBy: "user_current", // Required field
objectType: "contact" // Required field
}
});Retrieve
To retrieve an existing object, use the retrieve method with the entity’s unique ID.
const contact = await schemaTypeClient.retrieve(‘contact’, {
id: ‘ct_12345’,
});Update
To update an existing object, use the update method, providing the ID and the data to be changed.
const updatedContact = await schemaTypeClient.update('contact', {
id: 'ct_12345',
data: {
jobTitle: "Senior Software Engineer",
modifiedAt: Date.now(), // Required field (as a number)
modifiedBy: "user_current" // Required field
}
});Delete
To delete an object, use the delete method.
await schemaTypeClient.delete(‘contact’, {
id: ‘ct_12345’,
});Search
The search method allows you to find a list of objects of a schema type that match a given query. You can also handle pagination using rows and start.
const results = await schemaTypeClient.search(‘contact’, {
q: ‘John Doe’,
rows: 10, // Number of results to return
start: 0, // Starting offset for pagination });Search response payload
When you perform a search, the returned object follows a PaginatedResponse structure, containing the list of results and pagination details.
// Example for a contact search
{
"list": [
{
"contactId": "ct_12345",
"firstName": "John",
"lastName": "Doe",
"name": "John Doe",
// ...other contact fields
},
// ...other contact objects
],
"total": 100, // Total number of matching records
"start": 0, // The starting offset of this result set
"rows": 10 // The number of rows returned in this result setCustom requests
For specialized operations or schema types with custom links, you can use the generic request method. This gives you full control over the HTTP method, data payload, and URL path parameters.
const customResponse = await schemaTypeClient.request('myCustomSchema', 'myCustomLink', {
method: 'post',
data: {
foo: 'bar',
},
replacements: {
// for replacing path parameters in the URI, e.g. /myCustomSchema/{customId}/myCustomLink
customId: 'abcde',
},
});Error handling
All methods of the SchemaTypeClient return Promises. If an API request fails, the Promise will be rejected. You should always use try...catch blocks to handle errors gracefully.
try {
const contact = await schemaTypeClient.retrieve('contact', { id: 'non-existent-id' });
} catch (error) {
console.error('Failed to retrieve contact:', error);
// Example: display a user-friendly error message in the UI
}Permissions layer
Each Schema Type is protected by a permissions model that determines what actions are allowed for a given user or session.
Permissions scopes
Typical scopes include:
- read: Allows retrieving instances.
- write: Allows creating or updating instances.
- delete: Allows removing or archiving instances.
- admin: Grants full control, including configuration.
- Permissions can be defined at the schema type or object level (“users can read Contact but not Campaign”). If a user does not have access to a specific object, the API will return a 403 Forbidden error.
Advanced topics
Developer experience
Schema Types are auto-generated into TypeScript interfaces and runtime validators, enabling a rich developer experience. Developers can:
- Inspect schemas at runtime to get fields and metadata: sdk.getSchemaType('user').getFields()
- Use schema metadata for tooling or dynamic UI generation.
- Enjoy type safety and autocompletion when using the SDK. Autocomplete is available for all known fields, though some fields may still be accessible even if they are not included in autocompletion.
Updated 18 days ago