
Setup Datamodel
Create Dataverse tables, columns, and relationships with OData v9.2 deep-insert JSON patterns instead of hand-writing fragile API payloads.
Install
npx skills add https://github.com/microsoft/power-platform-skills --skill setup-datamodelWhat is this skill?
- Preferred deep insert: single POST to EntityDefinitions with nested columns
- Full JSON templates for DisplayName, DisplayCollectionName, and Description localized labels (LanguageCode 1033)
- SchemaName convention with prefix and table name for Dataverse entities
- Points to shared odata-common.md for auth headers, token refresh, status codes, and retry logic
- Relationship creation patterns documented alongside table and column metadata
Adoption & trust: 78 installs on skills.sh; 349 GitHub stars; 3/3 security scanners passed (skills.sh audits).
Recommended Skills
Entra App Registrationmicrosoft/azure-skills
Azure Aigatewaymicrosoft/azure-skills
Lark Openapi Explorerlarksuite/cli
Supabasesupabase/agent-skills
Firebase Auth Basicsfirebase/agent-skills
Firebase Data Connectfirebase/agent-skills
Journey fit
Primary fit
Dataverse schema is backend foundation for Power Pages and model-driven apps before UI or deploy steps. Backend fits because the skill centers EntityDefinitions OData POSTs and relationship metadata, not PAC deploy or marketing pages.
Common Questions / FAQ
Is Setup Datamodel safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.
SKILL.md
READMESKILL.md - Setup Datamodel
# OData API Patterns for Dataverse Table Creation Reference document for the `setup-datamodel` skill. Contains full JSON body templates for creating tables, columns, and relationships via the Dataverse OData Web API (v9.2). > **Authentication, error handling, and retry patterns** are in the shared reference: `${CLAUDE_PLUGIN_ROOT}/references/odata-common.md`. Read that file first for headers, token refresh, HTTP status codes, and retry logic. --- ## Create Table with Columns (Deep Insert) Create a table and its columns in a single POST using deep insert. This is the preferred approach — it avoids multiple round-trips. **Endpoint:** `POST {envUrl}/api/data/v9.2/EntityDefinitions` ```json { "@odata.type": "Microsoft.Dynamics.CRM.EntityMetadata", "SchemaName": "<Prefix>_<TableName>", "DisplayName": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [ { "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "<Display Name>", "LanguageCode": 1033 } ] }, "DisplayCollectionName": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [ { "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "<Display Name Plural>", "LanguageCode": 1033 } ] }, "Description": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [ { "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "<Description>", "LanguageCode": 1033 } ] }, "HasActivities": false, "HasNotes": false, "OwnershipType": "UserOwned", "IsActivity": false, "Attributes": [ { "@odata.type": "Microsoft.Dynamics.CRM.StringAttributeMetadata", "SchemaName": "<Prefix>_Name", "DisplayName": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [ { "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "Name", "LanguageCode": 1033 } ] }, "IsPrimaryName": true, "RequiredLevel": { "Value": "ApplicationRequired" }, "MaxLength": 200, "FormatName": { "Value": "Text" } } ] } ``` **Important notes:** - `SchemaName` uses PascalCase with prefix: `Cr123_ProjectName` - `LogicalName` is auto-generated as lowercase: `cr123_projectname` - Every table must have exactly one column with `"IsPrimaryName": true` - `OwnershipType` can be `"UserOwned"` (supports security roles) or `"OrganizationOwned"` (shared across org) --- ## Column Type Mapping Each Dataverse column type requires a specific `@odata.type` and set of properties. Below is the mapping from the data-model-architect's type names to OData metadata types. ### SingleLine.Text (String) ```json { "@odata.type": "Microsoft.Dynamics.CRM.StringAttributeMetadata", "SchemaName": "<Prefix>_<ColumnName>", "DisplayName": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [{ "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "<Display Name>", "LanguageCode": 1033 }] }, "RequiredLevel": { "Value": "None" }, "MaxLength": 200, "FormatName": { "Value": "Text" } } ``` `FormatName` values: `Text`, `Email`, `Url`, `Phone`, `TextArea` ### MultiLine.Text (Memo) ```json { "@odata.type": "Microsoft.Dynamics.CRM.MemoAttributeMetadata", "SchemaName": "<Prefix>_<ColumnName>", "DisplayName": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [{ "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "<Display Name>", "LanguageCode": 1033 }] }, "RequiredLevel": { "Value": "None" }, "MaxLength": 10000, "Format": "TextArea" } ``` ### WholeNumber (Integer) ```json { "@odata.type": "Microsoft.Dynamics.CRM.IntegerAttributeMetadata", "SchemaName": "<Prefix>_<ColumnName>", "DisplayName": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [{