| name | data-api-builder-cli |
| description | Data API Builder CLI commands for init, add, update, export, and start. Use when asked to create a dab-config, add entities, configure REST/GraphQL endpoints, or run DAB locally via CLI. |
| license | MIT |
Data API Builder (DAB) CLI
This skill powers GitHub Copilot assistance for the Data API Builder (DAB) CLI tool. It provides conversational guidance for creating, configuring, validating, and running DAB projects that expose database objects as REST, GraphQL, and MCP endpoints.
Core Mental Model
DAB is driven by a JSON config file (typically dab-config.json) containing:
data-source: Database connection settings (type, connection string, provider options)
runtime: Endpoint configuration (REST/GraphQL/MCP paths, auth, CORS, host mode)
entities: Exposed tables/views/stored procedures with permissions, relationships, mappings, and policies
Recommended Workflow
dab init — Create baseline config
dab add — Add entities (tables/views/stored procedures)
dab update — Evolve entities (permissions, relationships, mappings, policies)
dab configure — Tune runtime and data-source settings
dab validate — Preflight validation checks
dab start — Run the DAB engine
Security Default
Always prefer environment variables for connection strings:
- Use
@env('ENV_VAR_NAME') in config/CLI arguments
- Ask user before inlining secrets
Command Reference
1. dab init — Initialize Configuration
Purpose: Create a new DAB configuration file. This is typically the first step in a project.
Syntax:
dab init [options]
Critical Behavior:
- Overwrites existing config files without merging
- Recommend git usage or backups before running
Must Collect (ask if missing):
--database-type (mssql, postgresql, mysql, cosmosdb_nosql, cosmosdb_postgresql)
--connection-string (direct value or @env('VAR_NAME'))
Common Options:
| Category | Option | Default | Description |
|---|
| File | --config, -c | dab-config.json | Output file path |
| Database | --database-type | (required) | Database engine type |
| --connection-string | @env('CONNECTION_STRING') | Connection string (supports @env()) |
| --set-session-context | false | Enable SQL Server session context (mssql only) |
| --cosmosdb_nosql-database | (required for cosmos) | Cosmos DB database name |
| --cosmosdb_nosql-container | (optional) | Cosmos DB container name |
| --graphql-schema | (required for cosmos) | GraphQL schema path for Cosmos DB NoSQL |
| REST | --rest.enabled | true | Enable REST endpoint |
| --rest.path | /api | REST endpoint prefix |
| --rest.request-body-strict | true | Enforce strict request validation |
| GraphQL | --graphql.enabled | true | Enable GraphQL endpoint |
| --graphql.path | /graphql | GraphQL endpoint prefix |
| --graphql.allow-introspection | (varies) | Allow schema introspection (true in dev, false in prod) |
| --graphql.multiple-create.enabled | false | Allow multiple create mutations |
| MCP | --mcp.enabled | true | Enable MCP endpoint (v1.7+) |
| --mcp.path | /mcp | MCP endpoint prefix |
| Host | --host-mode | Production | Development or Production |
| --cors-origin | (none) | Comma-separated allowed origins |
| --runtime.base-route | (none) | Global prefix for all endpoints |
| Auth | --auth.provider | (none) | Identity provider (e.g., AzureAD) |
| --auth.audience | (none) | JWT audience claim |
| --auth.issuer | (none) | JWT issuer claim |
Important: Don't mix --*.enabled flags with legacy --*.disabled flags for the same subsystem.
Examples:
dab init \
--database-type mssql \
--connection-string "@env('DATABASE_CONNECTION_STRING')"
dab init \
--database-type mssql \
--connection-string "@env('DATABASE_CONNECTION_STRING')" \
--rest.enabled true \
--graphql.enabled false
dab init \
--database-type mssql \
--connection-string "@env('DATABASE_CONNECTION_STRING')" \
--rest.enabled false \
--graphql.enabled false \
--mcp.enabled true \
--mcp.path "/mcp"
dab init \
--database-type mssql \
--connection-string "@env('DATABASE_CONNECTION_STRING')" \
--host-mode production \
--auth.provider AzureAD \
--auth.issuer "https://login.microsoftonline.com/{tenant-id}/v2.0" \
--auth.audience "https://example.com/api" \
--cors-origin "https://app.example.com"
What to Say Next:
"Config created! Next, add entities with dab add, then validate with dab validate."
2. dab add — Add Entity
Purpose: Add a new entity (table/view/stored procedure) to an existing config.
Syntax:
dab add <entity-name> [options]
Must Collect (ask if missing):
<entity-name> (logical API name, case-sensitive)
--source, -s (database object name, including schema)
--permissions, -p (at least one "role:actions" pair)
Source Types & Requirements:
| Source Type | --source.type | Key Fields Required? | Actions | Notes |
|---|
| Table | table (default) | No (auto-detected) | create, read, update, delete, * | Most common |
| View | view | Yes (via --source.key-fields) | create, read, update, delete, * | Must specify PK fields |
| Stored Procedure | stored-procedure | No | execute, * | Use --source.params for defaults |
Permission Model:
| Role | Description | Common Use |
|---|
anonymous | Unauthenticated users | Public read-only data |
authenticated | Any authenticated user | Protected resources |
| Custom roles | Per auth provider | Fine-grained access (e.g., admin, editor) |
Actions:
- Tables/Views:
create, read, update, delete, *
- Stored Procedures:
execute, *
Common Options:
| Category | Option | Description |
|---|
| Source | --source, -s | Database object name |
| --source.type | table, view, stored-procedure (default: table) |
| --source.key-fields | Primary key fields (required for views, comma-separated) |
| --source.params | Stored procedure default params (param:value,param:value) |
| Permissions | --permissions, -p | Role and actions (role:action1,action2) |
| REST | --rest | true, false, or custom path |
| --rest.methods | Stored procedures: allowed verbs (GET,POST,PUT,PATCH,DELETE) |
| GraphQL | --graphql | true, false, singular, or singular:plural |
| --graphql.operation | Stored procedures: query or mutation (default: mutation) |
| Fields | --fields.include | Comma-separated included fields (* = all) |
| --fields.exclude | Comma-separated excluded fields |
| --fields.name | Field names to describe (comma-separated, v1.7+) |
| --fields.alias | Field aliases (aligned to --fields.name, v1.7+) |
| --fields.description | Field descriptions (aligned to --fields.name, v1.7+) |
| --fields.primary-key | PK flags (aligned to --fields.name, v1.7+) |
| Cache | --cache.enabled | Enable caching |
| --cache.ttl | TTL in seconds |
| Description | --description | Entity description (v1.7+) |
| Parameters | --parameters.name | Stored procedures: parameter names (comma-separated, v1.7+) |
| --parameters.description | Parameter descriptions (aligned, v1.7+) |
| --parameters.required | Parameter required flags (aligned, v1.7+) |
| --parameters.default | Parameter default values (aligned, v1.7+) |
Examples:
dab add Product \
--source dbo.Products \
--source.type table \
--permissions "anonymous:read"
dab add ProductSummary \
--source dbo.vw_ProductSummary \
--source.type view \
--source.key-fields "ProductId,Region" \
--permissions "anonymous:read"
dab add GetProductsByCategory \
--source dbo.usp_GetProductsByCategory \
--source.type stored-procedure \
--permissions "anonymous:execute" \
--graphql.operation query \
--rest.methods GET,POST
dab add Products \
--source dbo.Products \
--permissions "anonymous:*" \
--fields.name "ProductID,ProductName,UnitPrice" \
--fields.alias "product_id,product_name,price" \
--fields.description "Unique identifier,Product display name,Unit price in USD" \
--fields.primary-key "true,false,false"
dab add GetOrdersByDateRange \
--source dbo.usp_GetOrdersByDateRange \
--source.type stored-procedure \
--permissions "authenticated:execute" \
--description "Retrieves orders within a date range" \
--parameters.name "StartDate,EndDate,CustomerID" \
--parameters.description "Start of range (inclusive),End of range (inclusive),Optional customer filter" \
--parameters.required "true,true,false" \
--parameters.default ",,null"
Common Mistake:
--permissions is not repeatable in dab add. To add multiple roles:
- Add entity with one role in
dab add
- Add additional roles with
dab update
What to Say Next:
"Entity added! Add more entities, or run dab validate to check the config."
3. dab update — Modify Entity
Purpose: Modify an existing entity's properties (permissions, relationships, mappings, policies, REST/GraphQL exposure, caching).
Syntax:
dab update <entity-name> [options]
Critical Behaviors:
- Entity must already exist (case-sensitive match)
--permissions updates or adds the specified role
--map replaces entire mapping set (not additive)
--fields.include/--fields.exclude replace existing field lists
Option Groups:
Source
| Option | Description |
|---|
--source, -s | Change database object |
--source.type | Change to table, view, or stored-procedure |
--source.key-fields | Update key fields (views/non-PK tables) |
--source.params | Update stored procedure default params |
Permissions & Policies
| Option | Description |
|---|
--permissions, -p | Add/update permissions for a role: "role:actions" |
--policy-database | OData-style filter injected in DB query |
--policy-request | Request-level policy evaluated before DB call |
Fields & Mappings
| Option | Description |
|---|
--fields.include | Set included fields (replaces existing) |
--fields.exclude | Set excluded fields (replaces existing) |
-m, --map | Field mappings dbField:apiField (replaces all mappings) |
--fields.name | Field names to describe (v1.7+) |
--fields.alias | Field aliases (v1.7+) |
--fields.description | Field descriptions (v1.7+) |
--fields.primary-key | PK flags (v1.7+) |
REST
| Option | Description |
|---|
--rest | Enable/disable or set custom path |
--rest.methods | Stored procedures: allowed HTTP verbs |
GraphQL
| Option | Description |
|---|
--graphql | Enable/disable or set singular:plural names |
--graphql.operation | Stored procedures: query or mutation |
Relationships
Relationships define how entities are connected (one-to-one, one-to-many, many-to-one, many-to-many).
| Option | Description |
|---|
--relationship | Relationship name (used in API responses) |
--cardinality | one or many (defines relationship type) |
--target.entity | Target entity name |
--relationship.fields | Field mappings sourceField:targetField (comma-separated for composite keys) |
--linking.object | Many-to-many join table (schema.table format) |
--linking.source.fields | Join table fields (source side, comma-separated) |
--linking.target.fields | Join table fields (target side, comma-separated) |
Relationship Types:
- One-to-one:
cardinality: "one" (e.g., User → Profile)
- One-to-many:
cardinality: "many" (e.g., Category → Products)
- Many-to-one:
cardinality: "one" (e.g., Product → Category)
- Many-to-many:
cardinality: "many" with linking.object (e.g., Students ↔ Courses)
Cache
| Option | Description |
|---|
--cache.enabled | Enable/disable caching |
--cache.ttl | TTL in seconds |
Parameters (Stored Procedures)
| Option | Description |
|---|
--parameters.name | Parameter names (v1.7+) |
--parameters.description | Parameter descriptions (v1.7+) |
--parameters.required | Parameter required flags (v1.7+) |
--parameters.default | Parameter default values (v1.7+) |
Other
| Option | Description |
|---|
--description | Update entity description (v1.7+) |
--config, -c | Config file path |
Examples:
dab update Product --permissions "admin:*"
dab update Product --permissions "authenticated:read,update"
dab update Product \
--map "ProductName:name,UnitPrice:price,UnitsInStock:stock"
dab update User \
--fields.exclude "PasswordHash,SecurityStamp,TwoFactorSecret"
dab update Product --rest "products"
dab update InternalData --graphql false
dab update Product --cache.enabled true --cache.ttl 300
dab update Category \
--relationship "products" \
--cardinality many \
--target.entity Product \
--relationship.fields "CategoryId:CategoryId"
dab update Student \
--relationship "courses" \
--cardinality many \
--target.entity Course \
--linking.object "dbo.Enrollments" \
--linking.source.fields "StudentId" \
--linking.target.fields "CourseId"
dab update Employee \
--relationship "manager" \
--cardinality one \
--target.entity Employee \
--relationship.fields "ManagerId:EmployeeId"
dab update Order \
--permissions "authenticated:read" \
--policy-database "@item.UserId eq @claims.userId"
dab update Order \
--permissions "authenticated:create" \
--policy-request "@item.Quantity gt 0 and @item.Quantity lt 100"
Common Mistakes:
- Entity name mismatch (case-sensitive)
- Incomplete relationship (missing
--cardinality or --target.entity)
- Wrong policy syntax (use OData-style expressions, not SQL)
- Using
--map without restating all desired mappings
What to Say Next:
"Entity updated! Run dab validate to check the changes."
4. dab configure — Update Runtime/Data-Source
Purpose: Modify runtime and data-source properties that are not entity-specific.
Syntax:
dab configure [options]
Key Behaviors:
- Does not change entities (use
dab update for that)
- Modifies global config: data-source, runtime endpoints, auth, host settings
When to Use:
- Update database connection settings
- Toggle/adjust REST/GraphQL/MCP runtime endpoints
- Configure authentication provider
- Set CORS origins
- Change host mode
What to Ask:
- Which config file?
- What to change?
- Data-source (database type, connection string)
- Runtime (REST/GraphQL/MCP paths, auth, host mode, CORS)
Best Practice:
Use small, focused dab configure commands to isolate failures.
Example Use Cases:
dab configure --connection-string "@env('NEW_CONNECTION_STRING')"
dab configure --mcp.enabled true --mcp.path "/mcp"
dab configure --cors-origin "https://app.example.com,https://admin.example.com"
dab configure --host-mode development
What to Say Next:
"Configuration updated! Run dab validate to verify changes."
5. dab validate — Validate Configuration
Purpose: Check DAB config for errors before starting the engine.
Syntax:
dab validate [--config <path>]
Options:
| Option | Default | Description |
|---|
--config, -c | dab-config.json | Config file path |
Validation Stages:
- Schema validation — JSON structure and schema compliance
- Config properties — Logical consistency of settings
- Permissions — Role/action/policy correctness
- Database connection — Connectivity and env var resolution
- Entity metadata — Database objects/columns/params/relationships exist
Exit Codes:
0 — Valid
- Non-zero — Invalid
Best Practices:
dab add Product --source dbo.Products --permissions "anonymous:read"
dab validate
dab validate && dab start
dab validate --config dab-config.production.json
On Validation Failure:
- Ask user for the first error from output
- Identify the failing stage (schema, permissions, connectivity, etc.)
- Suggest targeted fix using
dab update or dab configure
- Re-validate
What to Say Next:
"Validation passed! Start the engine with dab start."
6. dab start — Start Runtime
Purpose: Start the DAB engine and expose configured endpoints.
Syntax:
dab start [options]
Options:
| Option | Description |
|---|
--config, -c | Config file path |
--verbose | Enable verbose logging |
--no-https-redirect | Disable HTTP→HTTPS redirect |
--LogLevel <level> | Set log level (Debug, Information, Warning, Error) |
Prerequisites (check before starting):
- DAB CLI installed
- Config file exists
- Environment variables set (if using
@env())
- Config validated (
dab validate)
Success Indicators:
Examples:
dab start
dab start --config dab-config.production.json
dab start --verbose
dab start --LogLevel Debug
Important:
DAB does not hot-reload config. Restart the runtime to apply changes.
What to Say Next:
"DAB is running! Access endpoints at the displayed URL."
Conversational Decision Trees
User says: "init" or "create config"
Ask:
- Database type? (
mssql, postgresql, mysql, cosmosdb_nosql, cosmosdb_postgresql)
- Config file name? (default:
dab-config.json)
- Connection string inline or via
@env()? (recommend @env())
- Which endpoints? (REST, GraphQL, MCP — defaults to all enabled)
- Host mode? (
development or production)
- Auth provider? (optional:
AzureAD, etc.)
Offer template:
dab init \
--database-type mssql \
--connection-string "@env('DATABASE_CONNECTION_STRING')" \
--host-mode development
User says: "add entity" or "add table/view/stored procedure"
Ask:
- Entity name? (logical API name)
- Source object? (include schema, e.g.,
dbo.Products)
- Source type? (
table, view, stored-procedure)
- Key fields? (required for views)
- Permissions? (at least one
role:actions pair)
- REST/GraphQL exposure? (enable/disable, custom naming)
Offer templates:
dab add Product \
--source dbo.Products \
--permissions "anonymous:read"
dab add ProductSummary \
--source dbo.vw_ProductSummary \
--source.type view \
--source.key-fields "ProductId" \
--permissions "anonymous:read"
dab add GetProducts \
--source dbo.usp_GetProducts \
--source.type stored-procedure \
--permissions "anonymous:execute" \
--graphql.operation query
User says: "change entity" or "update entity"
Ask:
- Which entity?
- What to change?
- Permissions (add/update role)
- Relationships (define/update)
- Mappings (rename fields)
- Policies (row-level security)
- REST/GraphQL exposure
- Caching
- Field inclusion/exclusion
Offer targeted commands based on answer.
User says: "add relationship" or "connect entities"
Ask:
- Source entity name?
- Target entity name?
- Relationship name? (how it appears in API, e.g., "products", "category", "courses")
- Relationship type?
- One-to-many: Parent has many children (e.g., Category → Products)
- Many-to-one: Child belongs to parent (e.g., Product → Category)
- One-to-one: Single record to single record (e.g., User → Profile)
- Many-to-many: Requires join table (e.g., Students ↔ Courses)
- Which fields connect them? (foreign key to primary key)
- For many-to-many: What's the join table name?
Offer templates:
dab update Category \
--relationship "products" \
--cardinality many \
--target.entity Product \
--relationship.fields "CategoryId:CategoryId"
dab update Product \
--relationship "category" \
--cardinality one \
--target.entity Category \
--relationship.fields "CategoryId:CategoryId"
dab update Student \
--relationship "courses" \
--cardinality many \
--target.entity Course \
--linking.object "dbo.Enrollments" \
--linking.source.fields "StudentId" \
--linking.target.fields "CourseId"
dab update Employee \
--relationship "manager" \
--cardinality one \
--target.entity Employee \
--relationship.fields "ManagerId:EmployeeId"
User says: "configure" or "change runtime"
Ask:
- Which config file?
- What to change?
- Database connection
- REST/GraphQL/MCP settings
- Auth provider
- CORS origins
- Host mode
Confirm it's not an entity change (use dab update for that).
User says: "validate" or "check config"
Ask:
- Which config file? (default:
dab-config.json)
- Are required env vars set?
If validation fails:
- Ask for first error from output
- Identify stage (schema, permissions, connectivity, etc.)
- Suggest fix
User says: "start" or "run"
Ask:
- Which config file?
- Are env vars set?
- Has config been validated?
Offer:
dab validate && dab start
Quick Reference Templates
New Project
dab init \
--database-type mssql \
--connection-string "@env('DATABASE_CONNECTION_STRING')" \
--host-mode development
dab add Product \
--source dbo.Products \
--permissions "anonymous:read"
dab validate && dab start
Common Patterns
Add Table with Multiple Roles
dab add Product --source dbo.Products --permissions "anonymous:read"
dab update Product --permissions "authenticated:*"
dab update Product --permissions "admin:*"
One-to-Many Relationship (Parent → Children)
dab update Category \
--relationship "products" \
--cardinality many \
--target.entity Product \
--relationship.fields "CategoryId:CategoryId"
Many-to-One Relationship (Child → Parent)
dab update Product \
--relationship "category" \
--cardinality one \
--target.entity Category \
--relationship.fields "CategoryId:CategoryId"
Bidirectional Relationships (Both Directions)
dab update Category \
--relationship "products" \
--cardinality many \
--target.entity Product \
--relationship.fields "CategoryId:CategoryId"
dab update Product \
--relationship "category" \
--cardinality one \
--target.entity Category \
--relationship.fields "CategoryId:CategoryId"
Many-to-Many Relationship (via Join Table)
dab update Student \
--relationship "courses" \
--cardinality many \
--target.entity Course \
--linking.object "dbo.Enrollments" \
--linking.source.fields "StudentId" \
--linking.target.fields "CourseId"
dab update Course \
--relationship "students" \
--cardinality many \
--target.entity Student \
--linking.object "dbo.Enrollments" \
--linking.source.fields "CourseId" \
--linking.target.fields "StudentId"
Self-Referencing Relationship (Hierarchy)
dab update Employee \
--relationship "manager" \
--cardinality one \
--target.entity Employee \
--relationship.fields "ManagerId:EmployeeId"
dab update Employee \
--relationship "directReports" \
--cardinality many \
--target.entity Employee \
--relationship.fields "EmployeeId:ManagerId"
Composite Key Relationship
dab update OrderItem \
--relationship "order" \
--cardinality one \
--target.entity Order \
--relationship.fields "OrderId:OrderId,LineNumber:LineNumber"
Row-Level Security
dab update Order \
--permissions "authenticated:read" \
--policy-database "@item.UserId eq @claims.userId"
REST-Only Endpoint
dab init \
--database-type mssql \
--connection-string "@env('DATABASE_CONNECTION_STRING')" \
--rest.enabled true \
--graphql.enabled false \
--mcp.enabled false
MCP-Only Endpoint (Agent Scenarios)
dab init \
--database-type mssql \
--connection-string "@env('DATABASE_CONNECTION_STRING')" \
--rest.enabled false \
--graphql.enabled false \
--mcp.enabled true
Consistency Rules
- Always recommend
dab validate before dab start
- Use environment variables for connection strings (security)
- Require
.gitignore with .env, **\bin, and **\obj entries before adding secrets
- Azure deployments: build custom Docker image with embedded
dab-config.json pushed to ACR — never use Azure Files, storage accounts, or volume mounts
- Stored procedures use
execute permission, not read
- Views require explicit key fields via
--source.key-fields
- Field mappings (
--map) replace all existing mappings (not additive)
- Entity changes use
dab update, runtime changes use dab configure
- Permissions in
dab add are not repeatable — add first role in dab add, others in dab update
- Policy syntax is OData-style, not SQL (e.g.,
eq, gt, and, @item, @claims)
- Relationships are defined on source entity via
dab update (not dab add)
- Cardinality
many creates array, one creates nested object in API responses
- Many-to-many requires junction table specified via
--linking.object
- Both entities must exist before creating relationships between them
Common Troubleshooting
"Entity doesn't exist"
- Check entity name (case-sensitive)
- Verify entity was added with
dab add
"Relationship target entity not found"
- Ensure target entity exists in config
- Check entity name spelling (case-sensitive)
- Cannot reference entities in different config files (multi-file limitation)
"Relationship validation failed"
- Verify field names match actual database columns
- Check that source and target fields are compatible types
- For many-to-many: ensure linking table exists
- Ensure both source and target fields are specified
"Validation failed: connection"
- Verify environment variable is set
- Check connection string format
- Test database connectivity
"Validation failed: permissions"
- Check role names (match auth provider roles)
- Verify action names (
create, read, update, delete, execute, *)
- Check policy syntax (OData-style)
"Validation failed: entity metadata"
- Verify database object exists (table/view/stored procedure)
- Check schema name (e.g.,
dbo.TableName)
- For views: ensure
--source.key-fields are specified
"Runtime won't start"
- Run
dab validate first
- Check port availability
- Verify environment variables are set
Version-Specific Features
v1.7+ Only (RC/Prerelease)
--description (entity and field descriptions)
--fields.name, --fields.alias, --fields.description, --fields.primary-key
--parameters.name, --parameters.description, --parameters.required, --parameters.default
--mcp.enabled, --mcp.path (MCP endpoint support)
To install v1.7 RC:
dotnet tool install microsoft.dataapibuilder --prerelease
References