Skip to content

Centrali Structures API Guide

This comprehensive guide covers everything you need to know about creating, updating, and retrieving structures in Centrali, including all validation rules, property types, and working examples.

Table of Contents


Overview

Structures in Centrali define the schema for your data records. They specify what fields (properties) your records can have, their data types, validation rules, and constraints. Think of structures as database table schemas or JSON schemas.

Key Concepts: - Structure: A schema definition that describes the shape of your data - Properties: Individual fields in a structure (like columns in a database) - Record Slug: A unique identifier for the type of records this structure describes - Strict Mode: Whether records can have additional fields not defined in the structure - Versioning: Track changes to structures over time


Authentication

All structure API requests require authentication via JWT token. See the Service Account Authentication Guide for details on obtaining tokens.

Headers Required:

Authorization: Bearer <your-jwt-token>
Content-Type: application/json


Structure Basics

Structure Object Schema

{
  "id": "uuid",                           // Auto-generated UUID
  "workspaceSlug": "string",              // Your workspace identifier
  "recordSlug": "string",                 // Unique identifier for records of this type
  "name": "string",                       // Human-readable name
  "description": "string",                // Optional description
  "properties": [...],                    // Array of property definitions (see below)
  "status": "active" | "inactive",        // Structure status
  "isStrict": boolean,                    // Whether to allow extra fields in records
  "enableVersioning": boolean,            // Enable structure version tracking
  "retentionPolicy": {...},               // Optional retention policy for versions
  "defaultSearchField": "string",         // Default field for text search
  "metadata": {...},                      // System metadata (read-only)
  "tags": ["string"],                     // Tags for security/categorization
  "createdBy": "string",                  // Creator user ID
  "lastUpdatedBy": "string",              // Last modifier user ID
  "createdAt": "datetime",                // Creation timestamp
  "updatedAt": "datetime",                // Last update timestamp
  "isDeleted": boolean                    // Soft delete flag
}

Required Fields

  • name: Structure name (cannot be empty)
  • properties: Array of property definitions (can be empty)
  • recordSlug: Unique identifier (auto-generated from name if not provided)

Optional Fields

  • description: Structure description
  • isStrict: Default is false (allows extra fields)
  • enableVersioning: Default is false
  • status: Default is "active"
  • defaultSearchField: Used for text search operations
  • retentionPolicy: Version retention configuration
  • tags: Array of tags for security

Property Types

Each property in a structure must specify a type. Centrali supports six core property types.

Common Property Fields

All property types share these base fields:

{
  "id": "string",              // Auto-generated unique ID (optional on create)
  "name": "string",            // Field name (required)
  "type": "string",            // Property type (required)
  "description": "string",     // Optional description
  "required": boolean,         // Is this field required? (default: false)
  "nullable": boolean,         // Can this field be null? (default: false)
  "default": any,              // Default value if not provided
  "enum": [...],               // Restrict to specific values
  "isUnique": boolean,         // Must values be unique? (default: false)
  "immutable": boolean         // Can't be changed after creation (default: false)
}

String Properties

Type: "string"

Additional Fields:

{
  "type": "string",
  "minLength": number,         // Minimum string length
  "maxLength": number,         // Maximum string length
  "pattern": "regex",          // Regular expression pattern
  "renderAs": "textarea" | "secret" | "color" | "code" | "html" | "markdown",
  "not": [...]                 // Array of disallowed values
}

Validation Rules: - minLength must be ≤ maxLength - pattern must be a valid regex - enum values must all be strings matching constraints - default must satisfy minLength, maxLength, and pattern - not values cannot overlap with enum or default

Example:

{
  "name": "email",
  "type": "string",
  "description": "User email address",
  "required": true,
  "minLength": 5,
  "maxLength": 255,
  "pattern": "^[\\w.-]+@[\\w.-]+\\.[a-zA-Z]{2,}$",
  "isUnique": true
}

Example with Enum:

{
  "name": "status",
  "type": "string",
  "enum": ["draft", "published", "archived"],
  "default": "draft",
  "required": true
}

Example with renderAs:

{
  "name": "description",
  "type": "string",
  "renderAs": "markdown",
  "maxLength": 5000
}

Number Properties

Type: "number"

Additional Fields:

{
  "type": "number",
  "minimum": number,           // Minimum value (inclusive by default)
  "maximum": number,           // Maximum value (inclusive by default)
  "exclusiveMinimum": boolean, // Make minimum exclusive (default: false)
  "exclusiveMaximum": boolean, // Make maximum exclusive (default: false)
  "multipleOf": number,        // Value must be a multiple of this
  "expression": "string",      // Computed field expression
  "computedMode": "persisted" | "virtual",
  "autoIncrement": {           // Auto-increment configuration
    "startAt": number,
    "incrementBy": number      // Default: 1
  }
}

Validation Rules: - minimum must be ≤ maximum - multipleOf must be a positive number - enum values must satisfy min/max/multipleOf constraints - default must satisfy all numeric constraints - If exclusiveMinimum is true, values must be > minimum (not >=) - If exclusiveMaximum is true, values must be < maximum (not <=) - autoIncrement.startAt and incrementBy must be numbers

Example:

{
  "name": "price",
  "type": "number",
  "description": "Product price in USD",
  "required": true,
  "minimum": 0,
  "exclusiveMinimum": true,
  "multipleOf": 0.01
}

Example with Enum:

{
  "name": "rating",
  "type": "number",
  "enum": [1, 2, 3, 4, 5],
  "required": true
}

Example with Auto-Increment:

{
  "name": "orderNumber",
  "type": "number",
  "autoIncrement": {
    "startAt": 1000,
    "incrementBy": 1
  },
  "required": true
}

Boolean Properties

Type: "boolean"

Additional Fields:

{
  "type": "boolean",
  "default": true | false,
  "enum": [true, false]        // Usually not needed for boolean
}

Validation Rules: - default must be a boolean - enum values (if provided) must be boolean

Example:

{
  "name": "isActive",
  "type": "boolean",
  "description": "Whether the item is active",
  "default": true,
  "required": true
}

DateTime Properties

Type: "datetime"

Additional Fields:

{
  "type": "datetime",
  "earliestDate": "ISO8601",   // Earliest allowed date
  "latestDate": "ISO8601",     // Latest allowed date
  "exclusiveEarliest": boolean,// Make earliest exclusive
  "exclusiveLatest": boolean,  // Make latest exclusive
  "expression": "string",      // Computed field expression
  "computedMode": "persisted" | "virtual"
}

Validation Rules: - Dates must be in ISO 8601 format (e.g., "2025-01-15T10:30:00Z") - earliestDate must be before latestDate - default must be a valid ISO 8601 datetime - enum values must be valid ISO 8601 datetimes - All dates must satisfy earliest/latest constraints

Example:

{
  "name": "birthDate",
  "type": "datetime",
  "description": "User birth date",
  "earliestDate": "1900-01-01T00:00:00Z",
  "latestDate": "2010-12-31T23:59:59Z",
  "required": true
}

Example with Default:

{
  "name": "createdAt",
  "type": "datetime",
  "description": "Record creation timestamp",
  "default": "2025-01-15T00:00:00Z",
  "immutable": true
}

Array Properties

Type: "array"

Additional Fields:

{
  "type": "array",
  "items": {                   // Item type definition (required)
    "type": "string" | "number" | "boolean" | "datetime" | "object"
  },
  "itemSchema": [...],         // Array of property definitions (required when items.type is "object")
  "isStrict": boolean,         // For object items: whether to allow extra properties (default: true)
  "minItems": number,          // Minimum array length
  "maxItems": number,          // Maximum array length
  "uniqueItems": boolean       // All items must be unique (default: false)
}

Validation Rules: - items.type is required and must be a valid type - items.type cannot be "array" (no nested arrays directly) - When items.type is "object", itemSchema must be provided with at least one property - itemSchema properties are validated using the same rules as top-level properties - Property names within itemSchema must be unique - minItems must be ≤ maxItems

Example (String Array):

{
  "name": "tags",
  "type": "array",
  "description": "Product tags",
  "items": {
    "type": "string"
  },
  "minItems": 1,
  "maxItems": 10,
  "uniqueItems": true
}

Example (Number Array):

{
  "name": "scores",
  "type": "array",
  "items": {
    "type": "number"
  },
  "minItems": 0,
  "maxItems": 100
}

Example (Array of Objects):

{
  "name": "contacts",
  "type": "array",
  "description": "List of contact persons",
  "items": {
    "type": "object"
  },
  "itemSchema": [
    {
      "name": "name",
      "type": "string",
      "required": true,
      "maxLength": 100
    },
    {
      "name": "email",
      "type": "string",
      "required": true,
      "pattern": "^[\\w.-]+@[\\w.-]+\\.[a-zA-Z]{2,}$"
    },
    {
      "name": "phone",
      "type": "string",
      "required": false,
      "pattern": "^\\+?[1-9]\\d{1,14}$"
    },
    {
      "name": "isPrimary",
      "type": "boolean",
      "default": false
    }
  ],
  "isStrict": true,
  "minItems": 1,
  "maxItems": 5
}

Note on Object Arrays: - When items.type is "object", the itemSchema field defines the structure of each object in the array - Each object in the array will be validated against the itemSchema - Use isStrict: true (default) to reject objects with extra properties not defined in itemSchema - Use isStrict: false to allow additional properties beyond those in itemSchema - Properties in itemSchema can have all the same constraints as top-level properties (required, default, validation rules, etc.)


Object Properties

Type: "object"

Additional Fields:

{
  "type": "object",
  "properties": [...],         // Array of nested property definitions
  "requiredProperties": [...], // Names of required nested properties
  "isStrict": boolean          // Whether to allow extra fields (default: false)
}

Validation Rules: - Nested properties are validated recursively - Property names within an object must be unique - requiredProperties must reference existing properties - Nested properties can be any type (including nested objects)

Example:

{
  "name": "address",
  "type": "object",
  "description": "User address",
  "required": true,
  "properties": [
    {
      "name": "street",
      "type": "string",
      "required": true,
      "maxLength": 100
    },
    {
      "name": "city",
      "type": "string",
      "required": true
    },
    {
      "name": "zipCode",
      "type": "string",
      "pattern": "^\\d{5}(-\\d{4})?$"
    },
    {
      "name": "country",
      "type": "string",
      "default": "USA"
    }
  ],
  "requiredProperties": ["street", "city"],
  "isStrict": false
}

API Operations

Create a Structure

Endpoint: POST /workspace/{workspaceSlug}/api/v1/structures

Request Body:

{
  "name": "Products",
  "description": "Product catalog structure",
  "recordSlug": "products",
  "isStrict": true,
  "enableVersioning": true,
  "properties": [
    {
      "name": "name",
      "type": "string",
      "required": true,
      "minLength": 3,
      "maxLength": 100
    },
    {
      "name": "price",
      "type": "number",
      "required": true,
      "minimum": 0,
      "exclusiveMinimum": true
    },
    {
      "name": "inStock",
      "type": "boolean",
      "default": true
    },
    {
      "name": "tags",
      "type": "array",
      "items": {
        "type": "string"
      },
      "uniqueItems": true
    }
  ]
}

curl Example:

curl -X POST "https://centrali.localhost/workspace/acme-corp/api/v1/structures" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Products",
    "description": "Product catalog structure",
    "recordSlug": "products",
    "isStrict": true,
    "properties": [
      {
        "name": "name",
        "type": "string",
        "required": true,
        "minLength": 3,
        "maxLength": 100
      },
      {
        "name": "price",
        "type": "number",
        "required": true,
        "minimum": 0
      }
    ]
  }'

Response (200 OK):

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "workspaceSlug": "acme-corp",
  "recordSlug": "products",
  "name": "Products",
  "description": "Product catalog structure",
  "properties": [
    {
      "id": "a1b2c3d4",
      "name": "name",
      "type": "string",
      "required": true,
      "minLength": 3,
      "maxLength": 100
    },
    {
      "id": "e5f6g7h8",
      "name": "price",
      "type": "number",
      "required": true,
      "minimum": 0
    }
  ],
  "status": "active",
  "isStrict": true,
  "enableVersioning": false,
  "isDeleted": false,
  "createdBy": "user-uuid-123",
  "lastUpdatedBy": "user-uuid-123",
  "createdAt": "2025-01-15T10:30:00Z",
  "updatedAt": "2025-01-15T10:30:00Z"
}

Notes: - recordSlug is auto-generated from name if not provided - Property id fields are auto-generated - The structure is automatically versioned if enableVersioning is true


Get a Structure

By ID

Endpoint: GET /workspace/{workspaceSlug}/api/v1/structures/{id}

curl -X GET "https://centrali.localhost/workspace/acme-corp/api/v1/structures/550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."

By Record Slug

Endpoint: GET /workspace/{workspaceSlug}/api/v1/structures/slug/{recordSlug}

curl -X GET "https://centrali.localhost/workspace/acme-corp/api/v1/structures/slug/products" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."

Response: Returns the structure object (same format as create response)


List Structures

Endpoint: GET /workspace/{workspaceSlug}/api/v1/structures

Query Parameters: - page (number): Page number (default: 1) - limit (number): Results per page (default: 500, max: 500) - search (string): Search term - searchField (string): Field to search on (default: "name") - sort[field] (string): Sort field - sort[direction] (string): "asc" or "desc" - filter[status] (string): Filter by status - filter[isDeleted] (boolean): Filter by deletion status

Example:

curl -X GET "https://centrali.localhost/workspace/acme-corp/api/v1/structures?page=1&limit=10&search=product&searchField=name" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."

Response:

{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "Products",
      "recordSlug": "products",
      "...": "..."
    }
  ],
  "meta": {
    "total": 1,
    "page": 1,
    "pageSize": 10
  }
}

Update a Structure

Endpoint: PUT /workspace/{workspaceSlug}/api/v1/structures/{id}

Important Notes: - Updating properties requires providing the full properties array - Each existing property must include its id field - To add a new property, set its id to "new" (it will be auto-generated) - Omitting a property from the array does NOT delete it; use the bulk delete endpoint

Request Body:

{
  "name": "Products Updated",
  "properties": [
    {
      "id": "a1b2c3d4",
      "name": "name",
      "type": "string",
      "required": true,
      "minLength": 5,
      "maxLength": 150
    },
    {
      "id": "e5f6g7h8",
      "name": "price",
      "type": "number",
      "required": true,
      "minimum": 0
    },
    {
      "id": "new",
      "name": "sku",
      "type": "string",
      "required": true,
      "isUnique": true
    }
  ]
}

curl Example:

curl -X PUT "https://centrali.localhost/workspace/acme-corp/api/v1/structures/550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Products Updated",
    "properties": [
      {
        "id": "a1b2c3d4",
        "name": "name",
        "type": "string",
        "required": true,
        "minLength": 5,
        "maxLength": 150
      }
    ]
  }'

Response: Returns the updated structure object


Delete a Structure

Soft Delete (Default)

Endpoint: DELETE /workspace/{workspaceSlug}/api/v1/structures/{id}

curl -X DELETE "https://centrali.localhost/workspace/acme-corp/api/v1/structures/550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."

Hard Delete (Permanent)

Endpoint: DELETE /workspace/{workspaceSlug}/api/v1/structures/{id}?hard=true

curl -X DELETE "https://centrali.localhost/workspace/acme-corp/api/v1/structures/550e8400-e29b-41d4-a716-446655440000?hard=true" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."

Response: Returns the deleted structure object


Validate a Structure

Test whether a structure definition is valid without creating it.

Endpoint: POST /workspace/{workspaceSlug}/api/v1/structures/validate

curl -X POST "https://centrali.localhost/workspace/acme-corp/api/v1/structures/validate" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Test Structure",
    "properties": [
      {
        "name": "email",
        "type": "string",
        "minLength": 5,
        "maxLength": 255
      }
    ]
  }'

Response (Valid):

{
  "valid": true,
  "errors": []
}

Response (Invalid):

{
  "valid": false,
  "errors": [
    {
      "field": "minLength",
      "message": "For property email Minimum length cannot exceed maximum length."
    }
  ]
}

Advanced Features

Retention Policies

Configure automatic cleanup of old structure versions:

{
  "retentionPolicy": {
    "maxVersions": 10,
    "maxAgeDays": 30,
    "cleanupIntervalHours": 24,
    "pinnedVersionsRetained": true
  }
}

Computed Fields

Create fields whose values are calculated from other fields:

{
  "name": "totalPrice",
  "type": "number",
  "expression": "price * quantity",
  "computedMode": "virtual"
}

Auto-Increment Fields

Automatically assign sequential numbers:

{
  "name": "invoiceNumber",
  "type": "number",
  "autoIncrement": {
    "startAt": 1000,
    "incrementBy": 1
  }
}

Structure History

Get the full version history of a structure:

Endpoint: GET /workspace/{workspaceSlug}/api/v1/structures/{id}/history

curl -X GET "https://centrali.localhost/workspace/acme-corp/api/v1/structures/550e8400-e29b-41d4-a716-446655440000/history" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."

Validation Rules

General Rules

  1. Unique Property Names: Property names must be unique within a structure
  2. Required Name: The name field is required for both structures and properties
  3. Type Required: Every property must have a valid type
  4. No Duplicate IDs: Property IDs must be unique

String Validation

  • minLengthmaxLength
  • pattern must be valid regex
  • enum values must be strings
  • default must satisfy all constraints
  • not array cannot contain default or enum values

Number Validation

  • minimummaximum
  • multipleOf must be positive
  • enum values must satisfy min/max/multipleOf
  • Exclusive bounds work as: value > min or value < max

DateTime Validation

  • All dates must be ISO 8601 format
  • earliestDate < latestDate
  • default and enum must satisfy date bounds

Array Validation

  • items.type is required
  • No nested arrays (array of arrays not supported)
  • minItemsmaxItems

Object Validation

  • Nested properties validated recursively
  • requiredProperties must reference existing properties
  • Nested object properties cannot have duplicate names

Common Errors

Error: "Missing required field name"

Cause: Structure or property missing the name field

Solution: Ensure every structure and property has a name field

{
  "name": "My Structure",
  "properties": [
    {
      "name": "myField",
      "type": "string"
    }
  ]
}

Error: "Duplicate property name 'email'"

Cause: Two properties have the same name

Solution: Ensure all property names are unique

Error: "For property price Minimum length cannot exceed maximum length"

Cause: minLength > maxLength (or minimum > maximum)

Solution: Fix the constraint values

{
  "name": "description",
  "type": "string",
  "minLength": 10,
  "maxLength": 500
}

Error: "Invalid regex pattern"

Cause: The pattern field contains invalid regex

Solution: Test your regex and escape special characters

{
  "name": "email",
  "type": "string",
  "pattern": "^[\\w.-]+@[\\w.-]+\\.[a-zA-Z]{2,}$"
}

Error: "Property 'type' is missing"

Cause: Property doesn't have a type field

Solution: Add the type field

{
  "name": "age",
  "type": "number"
}

Error: "Unsupported property type provided"

Cause: Invalid type value

Solution: Use one of: string, number, boolean, datetime, array, object

Error: "Structure with record slug 'products' already exists"

Cause: A structure with that recordSlug already exists

Solution: Use a different recordSlug or update the existing structure

Error: "Property ID is required"

Cause: When updating, existing properties must include their id

Solution: Include the id field for all existing properties, or use "new" for new properties

{
  "properties": [
    {
      "id": "a1b2c3d4",
      "name": "existingField",
      "type": "string"
    },
    {
      "id": "new",
      "name": "newField",
      "type": "number"
    }
  ]
}

Complete Examples

Example 1: E-Commerce Product Structure

curl -X POST "https://centrali.localhost/workspace/acme-corp/api/v1/structures" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Products",
    "description": "E-commerce product catalog",
    "recordSlug": "products",
    "isStrict": true,
    "enableVersioning": true,
    "properties": [
      {
        "name": "sku",
        "type": "string",
        "description": "Stock Keeping Unit",
        "required": true,
        "isUnique": true,
        "pattern": "^[A-Z]{3}-\\d{6}$",
        "immutable": true
      },
      {
        "name": "name",
        "type": "string",
        "description": "Product name",
        "required": true,
        "minLength": 3,
        "maxLength": 200
      },
      {
        "name": "description",
        "type": "string",
        "description": "Product description",
        "renderAs": "markdown",
        "maxLength": 5000
      },
      {
        "name": "price",
        "type": "number",
        "description": "Product price in USD",
        "required": true,
        "minimum": 0,
        "exclusiveMinimum": true,
        "multipleOf": 0.01
      },
      {
        "name": "compareAtPrice",
        "type": "number",
        "description": "Original price for comparison",
        "minimum": 0,
        "nullable": true
      },
      {
        "name": "inStock",
        "type": "boolean",
        "description": "Is product in stock",
        "default": true,
        "required": true
      },
      {
        "name": "category",
        "type": "string",
        "description": "Product category",
        "enum": ["electronics", "clothing", "books", "home", "toys"],
        "required": true
      },
      {
        "name": "tags",
        "type": "array",
        "description": "Product tags",
        "items": {
          "type": "string"
        },
        "uniqueItems": true,
        "maxItems": 10
      },
      {
        "name": "releaseDate",
        "type": "datetime",
        "description": "Product release date",
        "nullable": true
      },
      {
        "name": "specifications",
        "type": "object",
        "description": "Product specifications",
        "properties": [
          {
            "name": "weight",
            "type": "number",
            "description": "Weight in kg"
          },
          {
            "name": "dimensions",
            "type": "object",
            "properties": [
              {
                "name": "length",
                "type": "number"
              },
              {
                "name": "width",
                "type": "number"
              },
              {
                "name": "height",
                "type": "number"
              }
            ]
          },
          {
            "name": "color",
            "type": "string"
          },
          {
            "name": "material",
            "type": "string"
          }
        ]
      }
    ]
  }'

Example 2: User Profile Structure

curl -X POST "https://centrali.localhost/workspace/acme-corp/api/v1/structures" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "User Profiles",
    "recordSlug": "user-profiles",
    "isStrict": false,
    "properties": [
      {
        "name": "email",
        "type": "string",
        "required": true,
        "isUnique": true,
        "pattern": "^[\\w.-]+@[\\w.-]+\\.[a-zA-Z]{2,}$"
      },
      {
        "name": "firstName",
        "type": "string",
        "required": true,
        "minLength": 1,
        "maxLength": 50
      },
      {
        "name": "lastName",
        "type": "string",
        "required": true,
        "minLength": 1,
        "maxLength": 50
      },
      {
        "name": "birthDate",
        "type": "datetime",
        "earliestDate": "1900-01-01T00:00:00Z",
        "latestDate": "2010-12-31T23:59:59Z"
      },
      {
        "name": "phoneNumber",
        "type": "string",
        "pattern": "^\\+?[1-9]\\d{1,14}$",
        "nullable": true
      },
      {
        "name": "address",
        "type": "object",
        "properties": [
          {
            "name": "street",
            "type": "string",
            "required": true
          },
          {
            "name": "city",
            "type": "string",
            "required": true
          },
          {
            "name": "state",
            "type": "string"
          },
          {
            "name": "zipCode",
            "type": "string",
            "pattern": "^\\d{5}(-\\d{4})?$"
          },
          {
            "name": "country",
            "type": "string",
            "default": "USA",
            "required": true
          }
        ],
        "requiredProperties": ["street", "city", "country"]
      },
      {
        "name": "interests",
        "type": "array",
        "items": {
          "type": "string"
        },
        "uniqueItems": true
      },
      {
        "name": "isVerified",
        "type": "boolean",
        "default": false
      }
    ]
  }'

Example 3: Blog Post Structure with Auto-Increment

curl -X POST "https://centrali.localhost/workspace/acme-corp/api/v1/structures" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Blog Posts",
    "recordSlug": "blog-posts",
    "isStrict": true,
    "enableVersioning": true,
    "properties": [
      {
        "name": "postNumber",
        "type": "number",
        "description": "Sequential post number",
        "autoIncrement": {
          "startAt": 1,
          "incrementBy": 1
        },
        "required": true,
        "immutable": true
      },
      {
        "name": "title",
        "type": "string",
        "required": true,
        "minLength": 5,
        "maxLength": 150
      },
      {
        "name": "slug",
        "type": "string",
        "description": "URL-friendly slug",
        "required": true,
        "isUnique": true,
        "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
      },
      {
        "name": "content",
        "type": "string",
        "description": "Post content in markdown",
        "required": true,
        "renderAs": "markdown",
        "minLength": 100
      },
      {
        "name": "status",
        "type": "string",
        "enum": ["draft", "published", "archived"],
        "default": "draft",
        "required": true
      },
      {
        "name": "publishedAt",
        "type": "datetime",
        "nullable": true
      },
      {
        "name": "author",
        "type": "object",
        "required": true,
        "properties": [
          {
            "name": "id",
            "type": "string",
            "required": true
          },
          {
            "name": "name",
            "type": "string",
            "required": true
          },
          {
            "name": "email",
            "type": "string",
            "required": true
          }
        ],
        "requiredProperties": ["id", "name", "email"],
        "isStrict": true
      },
      {
        "name": "categories",
        "type": "array",
        "items": {
          "type": "string"
        },
        "minItems": 1,
        "maxItems": 5,
        "uniqueItems": true
      },
      {
        "name": "featured",
        "type": "boolean",
        "default": false
      },
      {
        "name": "viewCount",
        "type": "number",
        "minimum": 0,
        "default": 0
      }
    ],
    "retentionPolicy": {
      "maxVersions": 20,
      "maxAgeDays": 90,
      "cleanupIntervalHours": 24
    }
  }'

Support & Resources