# Complete example

Step-by-step guide to building a complete blog platform schema using the Hygraph Management SDK with best practices and error handling.

This guide walks you through building a complete blog platform schema using the Management SDK. You'll create models, components, relations, enumerations, and configure conditional visibility.

## What you'll build

A blog platform with:

- `Post` model with title, content, status, and a featured flag
- `Author` model with name, bio, and email
- `Category` model with name and description
- `SeoMetadata` component (reusable SEO fields)
- `AuthorInfo` component (social media info)
- `CallToAction` and `ImageBlock` components (content blocks)
- Post-to-Author relation (many-to-one)
- Post-to-Category relation (many-to-many)
- Component embeddings (SEO in Post, social info in `Author`)
- Modular component field (flexible content blocks)
- Nested components (ContactDetails nested inside `AuthorInfo`)
- Status enumeration (`DRAFT`, `REVIEW`, `PUBLISHED`)
- Conditional visibility rules

## Prerequisites

Before you begin, ensure that you have the following:

- Hygraph project created
- [Permanent Auth Token](https://hygraph.com/docs/getting-started/access-and-permissions/api-access#authenticated-requests-permanent-auth-tokens) with Management API permissions
- Node.js 18 or later installed
- Management SDK installed: `npm install @hygraph/management-sdk`
- Content API endpoint from **Project Settings > Endpoints > High Performance Content API**

## Dependency order

The Management SDK executes operations sequentially. You need to create dependencies before referencing them.

For example:
- Creating a relation before its target model exists will fail.
- Creating an enumerable field before its enumeration exists will fail.
- Embedding a component before it exists will fail.
- Nesting a component before the parent component exists will fail.

```

Create models (Author, Category, Post), and add simple fields to them
   ↓
Create enumerations (PostStatus)
   ↓
Add enumerable field (status) to Post
   ↓
Create components (SeoMetadata, AuthorInfo, CallToAction, ImageBlock), and add simple fields to them
   ↓
Embed components in models (SeoMetadata in Post, AuthorInfo in Author)
   ↓
Create nested components (ContactDetails nested inside AuthorInfo)
   ↓
Create modular component field (contentBlocks in Post)
   ↓
Create relations (Post→Author, Post→Category)
   ↓
Conditional visibility rules
```

## Initialize the client

Create the `create-blog-schema.ts` file:

```ts
import { Client } from '@hygraph/management-sdk';

const client = new Client({
  authToken: '',
  endpoint: '',
  name: 'create-blog-schema-v1', // Unique migration name
});

async function createBlogSchema() {
  try {
    // All operations will go here
  } catch (error) {
    console.error('Migration failed:', error);
    process.exit(1);
  }
}

createBlogSchema();
```

## Create models

Models must exist before you can add fields to them. The values of `apiId` and `apiIdPlural` must be different.

  **Author model**

```ts
// Create Author model
client.createModel({
  apiId: 'Author',
  apiIdPlural: 'Authors',
  displayName: 'Author',
  description: 'Blog post authors',
});

console.log('Created Author model');
```

  
  **Category model**

```ts
// Create Category model
client.createModel({
  apiId: 'Category',
  apiIdPlural: 'Categories',
  displayName: 'Category',
  description: 'Blog post categories',
});

console.log('Created Category model');
```

  
  **Post model**

```ts
// Create Post model
client.createModel({
  apiId: 'Post',
  apiIdPlural: 'Posts',
  displayName: 'Post',
  description: 'Blog posts',
});

console.log('Created Post model');
```


## Add fields to models

Now, you can add fields to your models. Note the following points:

- Only one field per model can be `isTitle: true`. This field appears as the entry identifier in the UI.
- `initialValue` sets the default for new entries.
- For boolean fields, use `true` or `false`.

  **Fields for Author model**

```ts
// Author: name (required, title field)
client.createSimpleField({
  parentApiId: 'Author',
  apiId: 'name',
  displayName: 'Name',
  type: SimpleFieldType.STRING,  // Use enum, not string
  isRequired: true,
  isTitle: true,
  visibility: VisibilityTypes.READ_WRITE,  // Optional but recommended
  description: 'Author full name',
});

// Author: email (required, unique)
client.createSimpleField({
  parentApiId: 'Author',
  apiId: 'email',
  displayName: 'Email',
  type: SimpleFieldType.STRING,  // Use enum
  isRequired: true,
  isUnique: true,
  visibility: VisibilityTypes.READ_WRITE,
  description: 'Author email address',
  validations: {
    String: {
      matches: {
        regex: '^([a-z0-9_\\.\\+-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$',
        errorMessage: 'Please enter a valid email address'
      }
    }
  }
});

// Author: bio (optional, rich text)
client.createSimpleField({
  parentApiId: 'Author',
  apiId: 'bio',
  displayName: 'Bio',
  type: SimpleFieldType.RICHTEXT,  // Use enum
  isRequired: false,
  visibility: VisibilityTypes.READ_WRITE,
  description: 'Author biography',
});

console.log('Added fields to Author');
```

  
  **Fields for Category model**

```ts
// Category: name (required, title field)
client.createSimpleField({
  parentApiId: 'Category',
  apiId: 'name',
  displayName: 'Name',
  type: SimpleFieldType.STRING,  // Use enum
  isRequired: true,
  isTitle: true,
  visibility: VisibilityTypes.READ_WRITE,
  description: 'Category name',
});

// Category: description
client.createSimpleField({
  parentApiId: 'Category',
  apiId: 'description',
  displayName: 'Description',
  type: SimpleFieldType.STRING,  // Use enum
  isRequired: false,
  visibility: VisibilityTypes.READ_WRITE,
  description: 'Category description',
});

console.log('Added fields to Category');
```

  
  **Fields for Post model**

```ts
// Post: title (required, title field)
client.createSimpleField({
  parentApiId: 'Post',
  apiId: 'title',
  displayName: 'Title',
  type: SimpleFieldType.STRING,  // Use enum
  isRequired: true,
  isTitle: true,
  visibility: VisibilityTypes.READ_WRITE,
  description: 'Post title',
});

// Post: slug (required, unique)
client.createSimpleField({
  parentApiId: 'Post',
  apiId: 'slug',
  displayName: 'Slug',
  type: SimpleFieldType.STRING,  // Use enum
  isRequired: true,
  isUnique: true,
  tableRenderer: 'GCMS_SLUG',
  formRenderer: 'GCMS_SLUG',
  visibility: VisibilityTypes.READ_WRITE,
  description: 'URL-friendly slug',
});

// Post: content (rich text)
client.createSimpleField({
  parentApiId: 'Post',
  apiId: 'content',
  displayName: 'Content',
  type: SimpleFieldType.RICHTEXT,  // Use enum
  isRequired: false,
  visibility: VisibilityTypes.READ_WRITE,
  description: 'Post content',
});

// Post: excerpt (optional)
client.createSimpleField({
  parentApiId: 'Post',
  apiId: 'excerpt',
  displayName: 'Excerpt',
  type: SimpleFieldType.STRING,  // Use enum
  isRequired: false,
  visibility: VisibilityTypes.READ_WRITE,
  description: 'Short summary for listings',
});

// Post: featured (boolean, default false)
client.createSimpleField({
  parentApiId: 'Post',
  apiId: 'featured',
  displayName: 'Featured',
  type: SimpleFieldType.BOOLEAN,  // Use enum
  isRequired: true,
  initialValue: 'false',  // String, not boolean!
  visibility: VisibilityTypes.READ_WRITE,
  description: 'Show in featured section',
});

console.log('Added fields to Post');
```


## Create an enumeration

Create an enumeration before configuring fields that reference them.

```ts
// Create PostStatus enumeration
client.createEnumeration({
  apiId: 'PostStatus',
  displayName: 'Post Status',
  description: 'Workflow status for blog posts',
  values: [
    { apiId: 'DRAFT', displayName: 'Draft' },
    { apiId: 'REVIEW', displayName: 'In Review' },
    { apiId: 'PUBLISHED', displayName: 'Published' },
  ],
});

console.log('Created PostStatus enumeration');
```

## Add enumeration to model

The enumeration, `PostStatus`, must already exist. The `initialValue` must match one of the enumeration's values.

```ts
// Post: status (enumerable field)
client.createEnumerableField({
  parentApiId: 'Post',
  apiId: 'status',
  displayName: 'Status',
  enumerationApiId: 'PostStatus',
  isRequired: true,
  initialValue: 'DRAFT',
  description: 'Publication status',
});

console.log('Added status enumeration to Post');
```

## Create components

Components are reusable field groups that can be embedded in multiple models. Create components before embedding them in models.

  **SEO Metadata component**

```ts
// Create SEO Metadata component
client.createComponent({
  apiId: 'SeoMetadata',
  apiIdPlural: 'SeoMetadatas',
  displayName: 'SEO Metadata',
  description: 'Search engine optimization fields',
});

console.log('Created SeoMetadata component');

// Add fields to the component
client.createSimpleField({
  parentApiId: 'SeoMetadata',
  apiId: 'metaTitle',
  displayName: 'Meta Title',
  type: SimpleFieldType.STRING,  // Use enum, not string
  isRequired: false,
  description: 'SEO title tag',
  validations: {
    String: {  // Wrap in String object
      characters: {
        max: 60,
        errorMessage: 'Meta title should be under 60 characters',
      },
    },
  },
});

client.createSimpleField({
  parentApiId: 'SeoMetadata',
  apiId: 'metaDescription',
  displayName: 'Meta Description',
  type: SimpleFieldType.STRING,  // Use enum
  isRequired: false,
  formRenderer: 'GCMS_MULTILINE',
  description: 'SEO meta description',
  validations: {
    String: {  // Wrap in String object
      characters: {
        max: 160,
        errorMessage: 'Meta description should be under 160 characters',
      },
    },
  },
});

client.createSimpleField({
  parentApiId: 'SeoMetadata',
  apiId: 'keywords',
  displayName: 'Keywords',
  type: SimpleFieldType.STRING,  // Use enum
  isList: true,
  isRequired: false,
  description: 'SEO keywords',
});

client.createSimpleField({
  parentApiId: 'SeoMetadata',
  apiId: 'noIndex',
  displayName: 'No Index',
  type: SimpleFieldType.BOOLEAN,  // Use enum
  isRequired: true,
  initialValue: 'false',  // String value, not boolean
  description: 'Prevent search engine indexing',
});

console.log('Added fields to SeoMetadata component');
```

  
  **AuthorInfo component**

```ts
// Create AuthorInfo component for flexible author details
client.createComponent({
  apiId: 'AuthorInfo',
  apiIdPlural: 'AuthorInfos',
  displayName: 'Author Info',
  description: 'Additional author information',
});

client.createSimpleField({
  parentApiId: 'AuthorInfo',
  apiId: 'website',
  displayName: 'Website',
  type: SimpleFieldType.STRING,  // Use enum
  isRequired: false,
  description: 'Author website URL',
});

client.createSimpleField({
  parentApiId: 'AuthorInfo',
  apiId: 'twitter',
  displayName: 'Twitter Handle',
  type: SimpleFieldType.STRING,  // Use enum
  isRequired: false,
  description: 'Twitter username',
});

client.createSimpleField({
  parentApiId: 'AuthorInfo',
  apiId: 'location',
  displayName: 'Location',
  type: SimpleFieldType.STRING,  // Use enum
  isRequired: false,
  description: 'Author location',
});

console.log('Created AuthorInfo component');
```

  
  **CallToAction component**

```ts
// Create components for page builder
client.createComponent({
  apiId: 'CallToAction',
  apiIdPlural: 'CallToActions',
  displayName: 'Call to Action',
  description: 'CTA block with button',
});

client.createSimpleField({
  parentApiId: 'CallToAction',
  apiId: 'heading',
  displayName: 'Heading',
  type: SimpleFieldType.STRING,  // Use enum
  isRequired: true,
  description: 'CTA heading',
});

client.createSimpleField({
  parentApiId: 'CallToAction',
  apiId: 'buttonText',
  displayName: 'Button Text',
  type: SimpleFieldType.STRING,  // Use enum
  isRequired: true,
  description: 'Button label',
});

client.createSimpleField({
  parentApiId: 'CallToAction',
  apiId: 'buttonUrl',
  displayName: 'Button URL',
  type: SimpleFieldType.STRING,  // Use enum
  isRequired: true,
  description: 'Button destination URL',
});

console.log('Created CallToAction component');
```

  
  **ImageBlock component**

```ts
// Create components for page builder
client.createComponent({
  apiId: 'ImageBlock',
  apiIdPlural: 'ImageBlocks',
  displayName: 'Image Block',
  description: 'Image with caption',
});

client.createSimpleField({
  parentApiId: 'ImageBlock',
  apiId: 'imageUrl',
  displayName: 'Image URL',
  type: SimpleFieldType.STRING,  // Use enum
  isRequired: true,
  description: 'Image source URL',
});

client.createSimpleField({
  parentApiId: 'ImageBlock',
  apiId: 'caption',
  displayName: 'Caption',
  type: SimpleFieldType.STRING,  // Use enum
  isRequired: false,
  description: 'Image caption',
});

client.createSimpleField({
  parentApiId: 'ImageBlock',
  apiId: 'altText',
  displayName: 'Alt Text',
  type: SimpleFieldType.STRING,  // Use enum
  isRequired: true,
  description: 'Accessibility text',
});

console.log('Created ImageBlock component');
```


## Embed component in model

Now let's embed the SEO component into the `Post` model. You can add SEO metadata to each post without duplicating fields across models.

```ts
// Post: Embed SeoMetadata component
client.createComponentField({
  parentApiId: 'Post',
  apiId: 'seo',
  displayName: 'SEO',
  componentApiId: 'SeoMetadata',
  isRequired: false,
  isList: false,
  description: 'SEO metadata for search engines',
});

console.log('Embedded SEO component in Post');
```

## Create modular component field

Modular components allow editors to choose from multiple component types, perfect for page builders. Editors can now add multiple `CallToAction` and `ImageBlock` components in any order within a post. A post might have:
- `ImageBlock`: A hero image or an infographic
- `CallToAction`: Subscribe prompt or download guide

```ts
// Post: Content blocks (modular component)
client.createComponentUnionField({
  parentApiId: 'Post',
  apiId: 'contentBlocks',
  displayName: 'Content Blocks',
  componentApiIds: ['CallToAction', 'ImageBlock'],
  isList: true,
  isRequired: false,
  description: 'Flexible content blocks for rich posts',
});

console.log('Created modular component field');
```

## Create nested components

Components can be nested inside other components for deeply hierarchical structures. Let's create a nested `Address` component. In this example, notice `parentApiId: 'AuthorInfo'`. We're nesting a component inside another component, not inside a model. This creates a two-level hierarchy: `Author → AuthorInfo → ContactDetails`.

```ts
// Create child component
client.createComponent({
  apiId: 'ContactDetails',
  apiIdPlural: 'ContactDetailsCollection',
  displayName: 'Contact Details',
  description: 'Phone and email contact information',
});

// Add fields to the component
client.createSimpleField({
  parentApiId: 'ContactDetails',
  apiId: 'phone',
  displayName: 'Phone',
  type: SimpleFieldType.STRING,
  isRequired: false,
  description: 'Contact phone number',
  visibility: VisibilityTypes.READ_WRITE
});

client.createSimpleField({
  parentApiId: 'ContactDetails',
  apiId: 'email',
  displayName: 'Email',
  type: SimpleFieldType.STRING,
  isRequired: true,  // Email is required
  description: 'Contact email address',
  validations: {
    String: {
      matches: {
        regex: '^([a-z0-9_\\.\\+-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$',
        errorMessage: 'Please enter a valid email address'
      }
    }
  }
});

console.log('Created ContactDetails component');

// Nest ContactDetails inside AuthorInfo component
client.createComponentField({
  parentApiId: 'AuthorInfo',
  apiId: 'contact',
  displayName: 'Contact',
  componentApiId: 'ContactDetails',
  isRequired: false,
  isList: false,  // Single contact (or true for multiple)
  description: 'Contact information',
  visibility: VisibilityTypes.READ_WRITE
});

console.log('Nested ContactDetails inside AuthorInfo');
```

**Result structure:**

```
Author (model)
  └── AuthorInfo (component)
    ├── website (STRING field)
    ├── twitter (STRING field)
    ├── location (STRING field)
    └── contact (component field) ← NESTED
        └── ContactDetails (component)
            ├── phone (STRING field)
            └── email (STRING field)
```

## Create a many-to-one reference

One author can write multiple posts. For this use case, we need to create a **many-to-one** relation.

```ts
client.createRelationalField({
  parentApiId: 'Post',
  apiId: 'author',
  displayName: 'Author',
  type: RelationalFieldType.RELATION,  // Use enum, not string
  reverseField: {
    apiId: 'posts',
    modelApiId: 'Author',  // Required! Specify the related model
    displayName: 'Posts',
    isList: true,  // Required! Author has many posts
    visibility: VisibilityTypes.READ_WRITE  // Use visibility instead of isHidden
  },
  isList: false,  // Post has one author
  isRequired: false,  // Cannot be required for RELATION type (only ASSET)
  description: 'Post author'
});

console.log('Created Post→Author relation');
```

## Create a many-to-many reference

A post can belong to multiple categories. A category can have multiple posts. For this use case, we need to create a **many-to-many** relation.

```ts
client.createRelationalField({
  parentApiId: 'Post',
  apiId: 'categories',
  displayName: 'Categories',
  type: RelationalFieldType.RELATION,  // Use enum, not string
  reverseField: {
    apiId: 'posts',
    modelApiId: 'Category',  // Required! Specify the related model here
    displayName: 'Posts',
    isList: true,  // Required! Category has many posts
    visibility: VisibilityTypes.READ_WRITE  // Use visibility instead of isHidden
  },
  isList: true,
  isRequired: false,
  description: 'Post categories'
});

console.log('Created Post→Category relation');
```

## Add conditional visibility

Make the `excerpt` field required only when `status` is `PUBLISHED`. Otherwise, it remains optional.

```ts
client.updateSimpleField({
  apiId: "excerpt",
  parentApiId: "Post",
  isRequired: true,
  visibility: VisibilityTypes.READ_WRITE,
  visibilityCondition: {
    baseField: "status", // API ID of the enumerable field (not the enum name)
    operator: FieldConditionOperator.IS,
    enumerationValues: ["PUBLISHED"],
    booleanValue: null
  }
});

console.log('Configured conditional visibility on excerpt');
```

## Advanced features

### Add a taxonomy

Taxonomies organize content into hierarchical categories. Let's add a category taxonomy and add the taxonomy to the `Post` model. Posts can now be organized using a hierarchical category tree.

```ts
// Create the taxonomy with all nodes at once
client.createTaxonomy({
  apiId: 'BlogCategories',
  displayName: 'Blog Categories',
  description: 'Hierarchical blog categorization',
  taxonomyNodes: [
    // Top-level categories (parent: null)
    { apiId: 'technology', displayName: 'Technology', parent: null },
    { apiId: 'business', displayName: 'Business', parent: null },
    // Subcategories
    { apiId: 'webDev', displayName: 'Web Development', parent: 'technology' },
    { apiId: 'aiMl', displayName: 'AI & Machine Learning', parent: 'technology' }
  ]
});

// Add taxonomy field to Post model
client.createTaxonomyField({
  parentApiId: 'Post',
  apiId: 'taxonomyCategories',
  displayName: 'Taxonomy Categories',
  taxonomyApiId: 'BlogCategories',
  isList: true,
  isRequired: false,
  description: 'Hierarchical categorization'
});

console.log('Created taxonomy and taxonomy field');

```

### Add a workflow

Create an editorial workflow for content approval. Posts can move through the draft → review → approved stages before publication.

```ts
client.createWorkflow({
  apiId: 'editorialWorkflow',
  displayName: 'Editorial Workflow',
  description: 'Content review and approval process',
  enabled: true,  // Required!
  steps: [  // Not "stages"!
    {
      apiId: 'draft',
      displayName: 'Draft',
      description: 'Work in progress',
      color: ColorPalette.BLUE,  // Use enum, not string
      allowEdit: true,  // Required!
      allowedRoles: ['role-id-1'],  // Required! Array of role IDs
      position: 0
    },
    {
      apiId: 'review',
      displayName: 'In Review',
      description: 'Awaiting editorial review',
      color: ColorPalette.YELLOW,  // Use enum
      allowEdit: false,  // Required!
      returnToStep: 'draft',  // Can return to draft if rejected
      allowedRoles: ['role-id-2'],  // Required!
      position: 1
    },
    {
      apiId: 'approved',
      displayName: 'Approved',
      description: 'Ready for publication',
      color: ColorPalette.GREEN,  // Use enum
      allowEdit: false,  // Required!
      allowedRoles: ['role-id-3'],  // Required!
      publishStages: ['published'],  // Optional: stages that can be published from this step
      position: 2
    },
  ],
});

console.log('Created editorial workflow');

```

### Add a webhook

Notify external systems when posts are published. Marketing system receives notifications when posts are published.

```ts
client.createWebhook({
  name: 'Post Publish Notification',
  description: 'Notify marketing system when blog posts are published',
  url: 'https://api.marketing.example.com/webhooks/blog-published',
  method: WebhookMethod.POST,
  headers: {
    Authorization: 'Bearer webhook-secret-token',
    'Content-Type': 'application/json',
  },
  isActive: true,
  includePayload: true,
  models: [],  // Empty array = all models (including future ones)
  stages: [],  // Empty array = all stages (including future ones)
  triggerType: WebhookTriggerType.CONTENT_MODEL,
  triggerActions: [WebhookTriggerAction.PUBLISH],
  secretKey: 'webhook-secret-key'
});
```

## Test with dry run

Before applying changes to production, test the migration:

```ts
// At the start of createBlogSchema(), before try block:
const changes = client.dryRun();

console.log('=== DRY RUN RESULTS ===');
console.log(`Operations: ${changes.length}`);
console.log(JSON.stringify(changes, null, 2));
console.log('======================');

// Exit without running
process.exit(0);
```

Review the output to ensure all operations are correct. Then remove the dry run code and proceed to production.

## Run the migration

```ts
async function createBlogSchema() {
  try {
    // ... all operations here ...

    // Execute migration
    const result = await client.run(true);

    if (result.errors) {
      console.error('Migration failed with errors:', result.errors);
      process.exit(1);
    }

    console.log('Migration completed successfully');
    console.log(`Migration name: ${result.name}`);
    console.log(`Finished at: ${result.finishedAt}`);
  } catch (error) {
    console.error('Migration failed:', error);
    process.exit(1);
  }
}
```

Run the script:

```bash
export HYGRAPH_AUTH_TOKEN="your-token"
export HYGRAPH_ENDPOINT="https://your-region.hygraph.com/v2/..."
node create-blog-schema.ts
```

## Integration test

Test the complete workflow:

1. **Create Author** with social info and nested contact details
2. **Create Categories**
3. **Create Post** with all features:
   - Set status to DRAFT (excerpt optional)
   - Fill in title, slug, content, featured flag
   - Select author and categories (relations)
   - Select taxonomy categories (hierarchical)
   - Add SEO metadata (metaTitle, metaDescription, keywords)
   - Add content blocks (CallToAction and ImageBlock components)
4. **Test conditional visibility:** Change status to PUBLISHED, verify excerpt becomes required
5. **Test workflow:** Move through stages if configured
6. **Test webhook:** Publish post and verify notification sent
7. **Verify final result:** Post displays with author (nested contact), categories, taxonomy, SEO, content blocks, and all features working together

## Troubleshooting

### Wrong operation order

Operations must be executed in the correct order. For example, creating a relation before the target model exists will fail.

  **Incorrect**

```ts
client.createRelationalField({
  parentApiId: 'Post',
  relatedModelApiId: 'Author', // Author doesn't exist yet
  // ...
});
client.createModel({ apiId: 'Author' /* ... */ });
```

  
  **Correct**

```ts
client.createModel({ apiId: 'Author' /* ... */ });
client.createRelationalField({
  parentApiId: 'Post',
  relatedModelApiId: 'Author', // Author exists now
  // ...
});
```


### Reused migration names

Use unique names for each migration, such as `create-blog-schema-v1`, `create-blog-schema-v2`, etc. Reusing names will cause the migration to fail.

```ts
const client = new Client({
  name: 'create-blog-schema', // First run: OK
  // Second run with same name: FAILS
});
```

### apiId and apiIdPlural are the same

The values of `apiId` and `apiIdPlural` of a model must be different.

  **Wrong**

```ts
client.createModel({
  apiId: 'Post',
  apiIdPlural: 'Post', // Must differ
});
```

  
  **Correct**

```ts
client.createModel({
  apiId: 'Post',
  apiIdPlural: 'Posts',
});
```


### Multiple title fields in a model

You can only have one `isTitle: true` field per model. This field is used as the entry identifier in the UI.

  **Wrong**

```ts
client.createSimpleField({
  parentApiId: 'Post',
  apiId: 'title',
  isTitle: true, // First title field - OK
});
client.createSimpleField({
  parentApiId: 'Post',
  apiId: 'name',
  isTitle: true, // Second title field - FAILS
});
```

  
  **Correct**

```ts
client.createSimpleField({
  parentApiId: 'Post',
  apiId: 'title',
  isTitle: true, // First title field - OK
});
client.createSimpleField({
  parentApiId: 'Post',
  apiId: 'name',
});
```


## Next steps

Review the [Methods Reference](https://hygraph.com/docs/api-reference/management-sdk/management-sdk-methods-reference) for all available Management SDK operations.
