
Fabric Cli
- 2 installs
- 36 repo stars
- Updated August 3, 2026
- data-goblin/fabric-cli-plugin
Use the Microsoft Fabric CLI (fab) to manage workspaces, semantic models, reports, notebooks, lakehouses, and OneLake files via a file-system metaphor.
About
Guides use of the Microsoft Fabric CLI (fab) to manage and automate Fabric resources like workspaces, semantic models, and lakehouses. A developer uses it to deploy items, run jobs, and query data, though this copy is marked deprecated in favor of the power-bi-agentic-development marketplace version.
- Manages Fabric workspaces, models, notebooks, and OneLake files
- Deprecated: use the fabric-cli plugin in power-bi-agentic-development
Fabric Cli by the numbers
- 2 all-time installs (skills.sh)
- Ranked #917 of 1,039 Cloud & Infrastructure skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/data-goblin/fabric-cli-plugin --skill fabric-cliAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 2 |
|---|---|
| repo stars | ★ 36 |
| Last updated | August 3, 2026 |
| Repository | data-goblin/fabric-cli-plugin ↗ |
What it does
Use the Microsoft Fabric CLI (fab) to manage workspaces, semantic models, reports, notebooks, lakehouses, and OneLake files via a file-system metaphor.
Files
DEPRECATED: This skill and thefabric-cli-pluginare deprecated. The actively maintained version lives in the power-bi-agentic-development marketplace under thefabric-cliplugin. Install it with:
```bash
claude plugin marketplace add data-goblin/power-bi-agentic-development
claude plugin install fabric-cli@power-bi-agentic-development
```
Microsoft Fabric CLI Operations
Note: If you have access to a Bash tool (e.g., Claude Code), execute fab commands directly via Bash rather than using an MCP server.Expert guidance for using the fab CLI to programmatically manage Fabric
When to Use This Skill
Activate automatically when tasks involve:
- Mention of the Fabric CLI, Fabric items, Power BI,
fab, orfabcommands - Managing workspaces, items, or resources
- Deploying or migrating semantic models, reports, notebooks, pipelines
- Running or scheduling jobs (notebooks, pipelines, Spark)
- Working with lakehouse/warehouse tables and data
- Using the Fabric, Power BI, or OneLake APIs
- Automating Fabric operations in scripts
Critical
- Before first use, ask the user if they have Fabric admin access, any API restrictions, or preferences for Fabric/Power BI API usage
- Remind the user to add their Fabric access level and preferences to their agent memory files (e.g., CLAUDE.md) for future sessions
- If workspace or item name is unclear, ask the user first, then verify with
fab lsorfab existsbefore proceeding - The first time you use
fabrunfab auth statusto make sure the user is authenticated. If not, ask the user to runfab auth loginto login - Always use
fab --helpandfab <command> --helpthe first time you use a command to understand its syntax, first - Always try the simple
fabcommand alone, first before piping it - Always use
-fwhen executing command if the flag is available to do so non-interactively - Ensure that you avoid removing or moving items, workspaces, or definitions, or changing properties without explicit user direction
- If a command is blocked in your permissions and you try to use it, stop and ask the user for clarification; never try to circumvent it
- Use
fabin non-interactive mode. Interactive mode doesn't work with coding agents
First Run
fab auth login # Authenticate (opens browser)
fab auth status # Verify authentication
fab ls # List your workspaces
fab ls "Name.Workspace" # List items in a workspaceVariable Extraction Pattern
Most workflows need IDs. Extract them like this:
WS_ID=$(fab get "ws.Workspace" -q "id" | tr -d '"')
MODEL_ID=$(fab get "ws.Workspace/Model.SemanticModel" -q "id" | tr -d '"')
# Then use in API calls
fab api -A powerbi "groups/$WS_ID/datasets/$MODEL_ID/refreshes" -X post -i '{"type":"Full"}'Quick Start
New to Fabric CLI? Here are some references you can read:
- Quick Start Guide - Copy-paste examples
- Querying Data - Query semantic models and lakehouse tables
- Semantic Models - TMDL, DAX, refresh, storage mode
- Reports - Export, import, visuals, fields
- Notebooks - Job execution, parameters
- Workspaces - Create, manage, permissions
- Folders - Organize items into folders via API (use
fab rmto delete items) - Full Command Reference - All commands detailed
- Command Reference Table - At-a-glance command syntax
Command Reference
| Command | Purpose | Example |
|---|---|---|
| Finding Items | ||
fab ls | List items | fab ls "Sales.Workspace" |
fab ls -l | List with details | fab ls "Sales.Workspace" -l |
fab exists | Check if exists | fab exists "Sales.Workspace/Model.SemanticModel" |
fab get | Get item details | fab get "Sales.Workspace/Model.SemanticModel" |
fab get -q | Query specific field | fab get "Sales.Workspace" -q "id" |
| Definitions | ||
fab get -q "definition" | Get full definition | fab get "ws.Workspace/Model.SemanticModel" -q "definition" |
fab export | Export to local | fab export "ws.Workspace/Nb.Notebook" -o ./backup |
fab import | Import from local | fab import "ws.Workspace/Nb.Notebook" -i ./backup/Nb.Notebook |
| Running Jobs | ||
fab job run | Run synchronously | fab job run "ws.Workspace/ETL.Notebook" |
fab job start | Run asynchronously | fab job start "ws.Workspace/ETL.Notebook" |
fab job run -P | Run with params | fab job run "ws.Workspace/Nb.Notebook" -P date:string=2025-01-01 |
fab job run-list | List executions | fab job run-list "ws.Workspace/Nb.Notebook" |
fab job run-status | Check status | fab job run-status "ws.Workspace/Nb.Notebook" --id <job-id> |
| Refreshing Models | ||
fab api -A powerbi | Trigger refresh | fab api -A powerbi "groups/<ws-id>/datasets/<model-id>/refreshes" -X post -i '{"type":"Full"}' |
fab api -A powerbi | Check refresh status | fab api -A powerbi "groups/<ws-id>/datasets/<model-id>/refreshes?\$top=1" |
| DAX Queries | ||
fab get -q "definition" | Get model schema first | fab get "ws.Workspace/Model.SemanticModel" -q "definition" |
fab api -A powerbi | Execute DAX | fab api -A powerbi "groups/<ws-id>/datasets/<model-id>/executeQueries" -X post -i '{"queries":[{"query":"EVALUATE..."}]}' |
| Lakehouse | ||
fab ls | Browse files/tables | fab ls "ws.Workspace/LH.Lakehouse/Files" |
fab table schema | Get table schema | fab table schema "ws.Workspace/LH.Lakehouse/Tables/sales" |
fab cp | Upload/download | fab cp ./local.csv "ws.Workspace/LH.Lakehouse/Files/" |
| Management | ||
fab cp | Copy items | fab cp "dev.Workspace/Item.Type" "prod.Workspace" -f |
fab set | Update properties | fab set "ws.Workspace/Item.Type" -q displayName -i "New Name" |
fab rm | Delete item | fab rm "ws.Workspace/Item.Type" -f |
Core Concepts
Path Format
Fabric uses filesystem-like paths with type extensions:
/WorkspaceName.Workspace/ItemName.ItemType
For lakehouses this is extended into files and tables:
/WorkspaceName.Workspace/LakehouseName.Lakehouse/Files/FileName.extension or /WorkspaceName.Workspace/LakehouseName.Lakehouse/Tables/TableName
For Fabric capacities you have to use fab ls .capacities
Examples:
"/Production.Workspace/Sales Model.SemanticModel"/Data.Workspace/MainLH.Lakehouse/Files/data.csv/Data.Workspace/MainLH.Lakehouse/Tables/dbo/customers
Common Item Types
.Workspace- Workspaces.SemanticModel- Power BI datasets.Report- Power BI reports.Notebook- Fabric notebooks.DataPipeline- Data pipelines.Lakehouse/.Warehouse- Data stores.SparkJobDefinition- Spark jobs
Full list: 35+ types. Use fab desc .<ItemType> to explore.
Essential Commands
Navigation & Discovery
# List resources
fab ls # List workspaces
fab ls "Production.Workspace" # List items in workspace
fab ls "Production.Workspace" -l # Detailed listing
fab ls "Data.Workspace/LH.Lakehouse" # List lakehouse contents
# Check existence
fab exists "Production.Workspace/Sales.SemanticModel"
# Get details
fab get "Production.Workspace/Sales.Report"
fab get "Production.Workspace" -q "id" # Query with JMESPathCreating & Managing Resources
# Create workspace after using `fab ls .capacities` to check capacities
fab mkdir "NewWorkspace.Workspace" -P capacityname=MyCapacity
# Create items
fab mkdir "Production.Workspace/NewLakehouse.Lakehouse"
fab mkdir "Production.Workspace/Pipeline.DataPipeline"
# Update properties
fab set "Production.Workspace/Item.Notebook" -q displayName -i "New Name"
fab set "Production.Workspace" -q description -i "Production environment"Copy, Move, Export, Import
# Copy between workspaces
fab cp "Dev.Workspace/Pipeline.DataPipeline" "Production.Workspace"
fab cp "Dev.Workspace/Report.Report" "Production.Workspace/ProdReport.Report"
# Export to local
fab export "Production.Workspace/Model.SemanticModel" -o /tmp/exports
fab export "Production.Workspace" -o /tmp/backup -a # Export all items
# Import from local
fab import "Production.Workspace/Pipeline.DataPipeline" -i /tmp/exports/Pipeline.DataPipeline -f
# IMPORTANT: Use -f flag for non-interactive execution
# Without -f, import/export operations expect an interactive terminal for confirmation
# This will fail in scripts, automation, or when stdin is not a terminal
fab import "ws.Workspace/Item.Type" -i ./Item.Type -f # Required for scriptsAPI Operations
Direct REST API access with automatic authentication.
Audiences:
fabric(default) - Fabric REST APIpowerbi- Power BI REST APIstorage- OneLake Storage APIazure- Azure Resource Manager
# Fabric API (default)
fab api workspaces
fab api workspaces -q "value[?type=='Workspace']"
fab api "workspaces/<workspace-id>/items"
# Power BI API (for DAX queries, dataset operations)
fab api -A powerbi groups
fab api -A powerbi "datasets/<model-id>/executeQueries" -X post -i '{"queries": [{"query": "EVALUATE VALUES(Date[Year])"}]}'
# POST/PUT/DELETE
fab api -X post "workspaces/<ws-id>/items" -i '{"displayName": "New Item", "type": "Lakehouse"}'
fab api -X put "workspaces/<ws-id>/items/<item-id>" -i /tmp/config.json
fab api -X delete "workspaces/<ws-id>/items/<item-id>"
# OneLake Storage API
fab api -A storage "WorkspaceName.Workspace/LH.Lakehouse/Files" -P resource=filesystem,recursive=falseJob Management
# Run synchronously (wait for completion)
fab job run "Production.Workspace/ETL.Notebook"
fab job run "Production.Workspace/Pipeline.DataPipeline" --timeout 300
# Run with parameters
fab job run "Production.Workspace/ETL.Notebook" -P date:string=2024-01-01,batch:int=1000,debug:bool=false
# Start asynchronously
fab job start "Production.Workspace/LongProcess.Notebook"
# Monitor
fab job run-list "Production.Workspace/ETL.Notebook"
fab job run-status "Production.Workspace/ETL.Notebook" --id <job-id>
# Schedule
fab job run-sch "Production.Workspace/Pipeline.DataPipeline" --type daily --interval 10:00,16:00 --start 2024-11-15T09:00:00 --enable
fab job run-sch "Production.Workspace/Pipeline.DataPipeline" --type weekly --interval 10:00 --days Monday,Friday --enable
# Cancel
fab job run-cancel "Production.Workspace/ETL.Notebook" --id <job-id>Table Operations
# View schema
fab table schema "Data.Workspace/LH.Lakehouse/Tables/dbo/customers"
# Load data (non-schema lakehouses only)
fab table load "Data.Workspace/LH.Lakehouse/Tables/sales" --file "Data.Workspace/LH.Lakehouse/Files/daily_sales.csv" --mode append
# Optimize (lakehouses only)
fab table optimize "Data.Workspace/LH.Lakehouse/Tables/transactions" --vorder --zorder customer_id,region
# Vacuum (lakehouses only)
fab table vacuum "Data.Workspace/LH.Lakehouse/Tables/temp_data" --retain_n_hours 48Common Workflows
Semantic Model Management
# Find models
fab ls "ws.Workspace" | grep ".SemanticModel"
# Get definition
fab get "ws.Workspace/Model.SemanticModel" -q definition
# Trigger refresh
fab api -A powerbi "groups/$WS_ID/datasets/$MODEL_ID/refreshes" -X post -i '{"type":"Full"}'
# Check refresh status
fab api -A powerbi "groups/$WS_ID/datasets/$MODEL_ID/refreshes?\$top=1"Execute DAX:
fab api -A powerbi "groups/$WS_ID/datasets/$MODEL_ID/executeQueries" -X post \
-i '{"queries":[{"query":"EVALUATE TOPN(5, '\''TableName'\'')"}]}'DAX rules: EVALUATE required, single quotes around tables ('Sales'), qualify columns ('Sales'[Amount]).
For full details: semantic-models.md | querying-data.md
Report Operations
# Get report definition
fab get "ws.Workspace/Report.Report" -q definition
# Export to local
fab export "ws.Workspace/Report.Report" -o /tmp/exports -f
# Import from local
fab import "ws.Workspace/Report.Report" -i /tmp/exports/Report.Report -f
# Rebind to different model
fab set "ws.Workspace/Report.Report" -q semanticModelId -i "<new-model-id>"For full details: reports.md
Lakehouse/Warehouse Operations
# Browse contents
fab ls "Data.Workspace/LH.Lakehouse/Files"
fab ls "Data.Workspace/LH.Lakehouse/Tables/dbo"
# Upload/download files
fab cp ./local-data.csv "Data.Workspace/LH.Lakehouse/Files/data.csv"
fab cp "Data.Workspace/LH.Lakehouse/Files/data.csv" ~/Downloads/
# Load and optimize tables
fab table load "Data.Workspace/LH.Lakehouse/Tables/sales" --file "Data.Workspace/LH.Lakehouse/Files/sales.csv"
fab table optimize "Data.Workspace/LH.Lakehouse/Tables/sales" --vorder --zorder customer_idEnvironment Migration
# Export from dev
fab export "Dev.Workspace" -o /tmp/migration -a
# Import to production (item by item)
fab import "Production.Workspace/Pipeline.DataPipeline" -i /tmp/migration/Pipeline.DataPipeline
fab import "Production.Workspace/Report.Report" -i /tmp/migration/Report.ReportCross-Workspace Search
DataHub V2 API (Recommended)
Use scripts/search_across_workspaces.py for cross-workspace search with rich metadata not available elsewhere:
# Find all semantic models (use "Model" not "SemanticModel")
python3 scripts/search_across_workspaces.py --type Model
# Find models by name
python3 scripts/search_across_workspaces.py --type Model --filter "Sales"
# Find stale items (not visited in 6+ months)
python3 scripts/search_across_workspaces.py --type Model --not-visited-since 2024-06-01
# Find items by owner
python3 scripts/search_across_workspaces.py --type PowerBIReport --owner "kurt"
# Find Direct Lake models only
python3 scripts/search_across_workspaces.py --type Model --storage-mode directlake
# Find items in workspace
python3 scripts/search_across_workspaces.py --type Lakehouse --workspace "fit-data"
# Get JSON output
python3 scripts/search_across_workspaces.py --type Model --output json
# Sort by last visited (oldest first)
python3 scripts/search_across_workspaces.py --type Model --sort last-visited --sort-order asc
# List all available types
python3 scripts/search_across_workspaces.py --list-typesUnique DataHub fields (not available via fab api or admin APIs):
lastVisitedTimeUTC- When item was last opened/usedstorageMode- Import, DirectQuery, or DirectLakeownerUser- Full owner details (name, email)capacitySku- F2, F64, PP, etc.isDiscoverable- Whether item appears in search
Important type mappings:
- Semantic models: use
--type Model(not SemanticModel) - Dataflows: use
--type DataFlow(capital F) - Notebooks: use
--type SynapseNotebook
Admin APIs (Requires Admin Role)
If you have Fabric/Power BI admin access:
# Find semantic models by name (cross-workspace)
fab api "admin/items" -P "type=SemanticModel" -q "itemEntities[?contains(name, 'Sales')]"
# Find all notebooks
fab api "admin/items" -P "type=Notebook" -q "itemEntities[].{name:name,workspace:workspaceId}"
# Find all lakehouses
fab api "admin/items" -P "type=Lakehouse"
# Common types: SemanticModel, Report, Notebook, Lakehouse, Warehouse, DataPipeline, OntologyFor full admin API reference: admin.md
Key Patterns
JMESPath Queries
Filter and transform JSON responses with -q:
# Get single field
-q "id"
-q "displayName"
# Get nested field
-q "properties.sqlEndpointProperties"
-q "definition.parts[0]"
# Filter arrays
-q "value[?type=='Lakehouse']"
-q "value[?contains(name, 'prod')]"
# Get first element
-q "value[0]"
-q "definition.parts[?path=='model.tmdl'] | [0]"Error Handling & Debugging
# Show response headers
fab api workspaces --show_headers
# Verbose output
fab get "Production.Workspace/Item" -v
# Save responses for debugging
fab api workspaces -o /tmp/workspaces.jsonPerformance Optimization
1. Use `ls` for fast listing - Much faster than get 2. Use `exists` before operations - Check before get/modify 3. Filter with `-q` - Get only what you need 4. Use GUIDs in automation - More stable than names
Common Flags
-f, --force- Skip confirmation prompts-v, --verbose- Verbose output-l- Long format listing-a- Show hidden items-o, --output- Output file path-i, --input- Input file or JSON string-q, --query- JMESPath query-P, --params- Parameters (key=value)-X, --method- HTTP method (get/post/put/delete/patch)-A, --audience- API audience (fabric/powerbi/storage/azure)--show_headers- Show response headers--timeout- Timeout in seconds
Important Notes
- All examples assume `fab` is installed and authenticated
- Paths require proper extensions (
.Workspace,.SemanticModel, etc.) - Quote paths with spaces:
"My Workspace.Workspace" - Use `-f` for non-interactive scripts (skips prompts)
- Semantic model updates: Use Power BI API (
-A powerbi) for DAX queries and dataset operations
Need More Details?
For specific item type help:
fab desc .<ItemType>For command help:
fab --help
fab <command> --helpReferences
Skill references:
- Querying Data - Query semantic models and lakehouse tables
- Semantic Models - TMDL, DAX, refresh, storage mode
- Reports - Export, import, visuals, fields
- Notebooks - Job execution, parameters
- Workspaces - Create, manage, permissions
- Admin APIs - Cross-workspace search, tenant operations, governance
- API Reference - Capacities, gateways, pipelines, domains, dataflows, apps
- Full Command Reference - All commands detailed
- Quick Start Guide - Copy-paste examples
External references (request markdown when possible):
- fab CLI: GitHub Source | Docs
- Microsoft: Fabric CLI Learn
- APIs: Fabric API | Power BI API
- DAX: dax.guide - use
dax.guide/<function>/e.g.dax.guide/addcolumns/ - Power Query: powerquery.guide - use
powerquery.guide/function/<function> - Power Query Best Practices
Power BI / Fabric Project
Automatic Skills
Always invoke fabric-cli skill when:
- Working with Power BI reports, semantic models, or datasets
- Managing Fabric workspaces, lakehouses, notebooks, pipelines
- Running
fabCLI commands or discussing Fabric APIs - Answering questions about Power BI or Microsoft Fabric
Fabric CLI Usage
fab auth status # Check authentication
fab ls # List workspaces
fab ls "ws.Workspace" # List items in workspace
fab --help # Command referenceCommon Patterns
- Always use
-fflag for non-interactive execution - Quote paths with spaces:
"My Workspace.Workspace" - Extract IDs for API calls:
fab get "ws.Workspace" -q "id" - Use
-qfor JMESPath queries on output
Safety
- Never remove/move items without explicit permission
- Verify workspace/item names with
fab lsorfab existsbefore operations - Check
fab auth statusbefore first use each session
Cross-Workspace Search
Use scripts/search_across_workspaces.py for finding items across workspaces:
python3 scripts/search_across_workspaces.py --type Model --filter "Sales"
python3 scripts/search_across_workspaces.py --list-typesReferences
Skill includes detailed references for:
- Semantic models, reports, notebooks, lakehouses
- DAX queries, Power BI API, admin operations
- Full command reference at
fab <command> --help
Admin API Operations
Guide for Fabric/Power BI admin-level API operations using fab. These APIs require admin privileges and enable cross-workspace discovery, tenant-wide operations, and governance.
Prerequisites
- Fabric Admin or Power BI Admin role
- Or delegated admin permissions via service principal
Check your access:
fab api "admin/capacities" 2>&1 | head -5
# If you see results, you have admin accessCross-Workspace Item Discovery
The admin API is the fastest way to find items across ALL workspaces without iterating.
Find Items by Type
# Find all semantic models across tenant
fab api "admin/items" -P "type=SemanticModel"
# Find all notebooks
fab api "admin/items" -P "type=Notebook"
# Find all lakehouses
fab api "admin/items" -P "type=Lakehouse"
# Find specific item by name pattern
fab api "admin/items" -P "type=SemanticModel" -q "itemEntities[?contains(name, 'Sales')]"Available Item Types
SemanticModel Report Dashboard Notebook
Lakehouse Warehouse DataPipeline Dataflow
Environment SparkJobDef CopyJob Reflex
Ontology GraphModel Exploration OrgAppExtract Item Details
# Get item IDs and workspace IDs
fab api "admin/items" -P "type=Lakehouse" -q "itemEntities[].{name:name,id:id,workspace:workspaceId}"
# Find item's workspace name
ITEM=$(fab api "admin/items" -P "type=SemanticModel" -q "itemEntities[?name=='Sales Model'] | [0]")
WS_ID=$(echo "$ITEM" | jq -r '.workspaceId')
fab api "admin/workspaces/$WS_ID" -q "displayName"Workspace Administration
List All Workspaces
# All workspaces in tenant
fab api "admin/workspaces"
# Filter by state
fab api "admin/workspaces" -q "workspaces[?state=='Active']"
# Get workspace details with users
fab api "admin/workspaces/<workspace-id>/users"Workspace Governance
# Get workspace capacity assignment
fab api "admin/workspaces/<workspace-id>" -q "capacityId"
# List workspaces on a capacity
fab api "admin/capacities/<capacity-id>/workspaces"Capacity Administration
# List all capacities
fab api "admin/capacities"
# Get capacity details
fab api "admin/capacities/<capacity-id>"
# Get capacity workloads
fab api "admin/capacities/<capacity-id>/workloads"Dataset/Model Administration
# Get all datasets in tenant (Power BI API)
fab api -A powerbi "admin/datasets"
# Get dataset users
fab api -A powerbi "admin/datasets/<dataset-id>/users"
# Get datasources for a dataset
fab api -A powerbi "admin/datasets/<dataset-id>/datasources"Report Administration
# Get all reports in tenant
fab api -A powerbi "admin/reports"
# Get report users
fab api -A powerbi "admin/reports/<report-id>/users"
# Get reports in a workspace
fab api -A powerbi "admin/groups/<workspace-id>/reports"Common Patterns
Find Item Across Workspaces
# Search for a model by name
fab api "admin/items" -P "type=SemanticModel" \
-q "itemEntities[?contains(name, 'keyword')] | [0].{name:name,id:id,workspace:workspaceId}"Get Full Item Path
# Get workspace name + item name for fab path
ITEM=$(fab api "admin/items" -P "type=Notebook" -q "itemEntities[?name=='ETL Pipeline'] | [0]")
WS_ID=$(echo "$ITEM" | jq -r '.workspaceId')
ITEM_NAME=$(echo "$ITEM" | jq -r '.name')
WS_NAME=$(fab api "admin/workspaces/$WS_ID" -q "displayName" | tr -d '"')
echo "$WS_NAME.Workspace/$ITEM_NAME.Notebook"Audit Item Modifications
# Get items modified recently
fab api "admin/items" -P "type=Report" \
-q "itemEntities | sort_by(@, &lastUpdatedDate) | reverse(@) | [:10]"Security & Governance
Get Item Permissions
# Dataset permissions
fab api -A powerbi "admin/datasets/<dataset-id>/users"
# Report permissions
fab api -A powerbi "admin/reports/<report-id>/users"
# Workspace permissions
fab api "admin/workspaces/<workspace-id>/users"Encryption Keys
# Get tenant encryption keys
fab api -A powerbi "admin/tenantKeys"Pagination
Admin APIs return paginated results. Check for continuation:
# First page
RESULT=$(fab api "admin/items" -P "type=SemanticModel")
# Check for more
echo "$RESULT" | jq '.continuationUri'
# If not null, fetch next page
fab api "<continuation-uri>"Error Handling
Common admin API errors:
| Error | Cause | Solution |
|---|---|---|
| 401 | Not authenticated | Run fab auth login |
| 403 | Not admin | Request admin role |
| 404 | Item not found | Check item exists |
| 429 | Rate limited | Wait and retry |
Best Practices
1. Cache results - Admin APIs can be slow; cache for repeated queries 2. Use filters - Always filter by type when possible 3. Paginate - Handle continuation for large tenants 4. Rate limit - Space out bulk operations 5. Audit - Log admin operations for compliance
Creating Workspaces
Create Workspace with Large Storage Format
Step 1: List available capacities
fab ls .capacitiesStep 2: Create workspace on chosen capacity
fab mkdir "Workspace Name.Workspace" -P capacityName="MyCapacity"Step 3: Get workspace ID
fab get "Workspace Name.Workspace" -q "id"Step 4: Set default storage format to Large
fab api -A powerbi -X patch "groups/<workspace-id>" -i '{"defaultDatasetStorageFormat":"Large"}'Done. The workspace now defaults to Large storage format for all new semantic models.
Fabric API Reference
Direct API access via fab api for operations beyond standard commands.
API Basics
# Fabric API (default)
fab api "<endpoint>"
# Power BI API
fab api -A powerbi "<endpoint>"
# With query
fab api "<endpoint>" -q "value[0].id"
# POST with body
fab api -X post "<endpoint>" -i '{"key":"value"}'Capacities
# List all capacities
fab api capacities
# Response includes: id, displayName, sku (F2, F64, FT1, PP3), region, statePause capacity (cost savings):
# CAUTION: Pausing stops all workloads on that capacity
# Resume is intentionally NOT documented - too dangerous for automation
# Use Azure Portal for resume operations
# To pause via Azure CLI (not fab):
az resource update --ids "/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Fabric/capacities/{name}" \
--set properties.state=PausedGateways
# List gateways
fab api -A powerbi gateways
# Get gateway datasources
GATEWAY_ID="<gateway-id>"
fab api -A powerbi "gateways/$GATEWAY_ID/datasources"
# Get gateway users
fab api -A powerbi "gateways/$GATEWAY_ID/users"Deployment Pipelines
# List pipelines (user)
fab api -A powerbi pipelines
# List pipelines (admin - all tenant)
fab api -A powerbi admin/pipelines
# Get pipeline stages
PIPELINE_ID="<pipeline-id>"
fab api -A powerbi "pipelines/$PIPELINE_ID/stages"
# Get pipeline operations
fab api -A powerbi "pipelines/$PIPELINE_ID/operations"Deploy content (use Fabric API):
# Assign workspace to stage
fab api -X post "deploymentPipelines/$PIPELINE_ID/stages/$STAGE_ID/assignWorkspace" \
-i '{"workspaceId":"<workspace-id>"}'
# Deploy to next stage
fab api -X post "deploymentPipelines/$PIPELINE_ID/deploy" -i '{
"sourceStageOrder": 0,
"targetStageOrder": 1,
"options": {"allowCreateArtifact": true, "allowOverwriteArtifact": true}
}'Domains
# List domains
fab api admin/domains
# Get domain workspaces
DOMAIN_ID="<domain-id>"
fab api "admin/domains/$DOMAIN_ID/workspaces"
# Assign workspaces to domain
fab api -X post "admin/domains/$DOMAIN_ID/assignWorkspaces" \
-i '{"workspacesIds":["<ws-id-1>","<ws-id-2>"]}'Dataflows
Gen1 (Power BI dataflows):
# List all dataflows (admin)
fab api -A powerbi admin/dataflows
# List workspace dataflows
WS_ID="<workspace-id>"
fab api -A powerbi "groups/$WS_ID/dataflows"
# Refresh dataflow
DATAFLOW_ID="<dataflow-id>"
fab api -A powerbi -X post "groups/$WS_ID/dataflows/$DATAFLOW_ID/refreshes"Gen2 (Fabric dataflows):
# Gen2 dataflows are Fabric items - use standard fab commands
fab ls "ws.Workspace" | grep DataflowGen2
fab get "ws.Workspace/Flow.DataflowGen2" -q "id"Apps
Workspace Apps (published from workspaces):
# List user's apps
fab api -A powerbi apps
# List all apps (admin)
fab api -A powerbi 'admin/apps?$top=100'
# Get app details
APP_ID="<app-id>"
fab api -A powerbi "apps/$APP_ID"
# Get app reports
fab api -A powerbi "apps/$APP_ID/reports"
# Get app dashboards
fab api -A powerbi "apps/$APP_ID/dashboards"Org Apps (template apps from AppSource):
# Org apps are installed from AppSource marketplace
# They appear in the regular apps endpoint after installation
# No separate API for org app catalog - use AppSourceAdmin Operations
Workspaces
# List all workspaces (requires $top)
fab api -A powerbi 'admin/groups?$top=100'
# Response includes: id, name, type, state, capacityId, pipelineId
# Get workspace users
fab api -A powerbi "admin/groups/$WS_ID/users"Items
# List all items in tenant
fab api admin/items
# Response includes: id, type, name, workspaceId, capacityId, creatorPrincipalSecurity Scanning
# Reports shared with entire org (security risk)
fab api -A powerbi "admin/widelySharedArtifacts/linksSharedToWholeOrganization"
# Reports published to web (security risk)
fab api -A powerbi "admin/widelySharedArtifacts/publishedToWeb"Activity Events
# Get activity events (last 30 days max)
# Dates must be in ISO 8601 format with quotes
START="2025-11-26T00:00:00Z"
END="2025-11-27T00:00:00Z"
fab api -A powerbi "admin/activityevents?startDateTime='$START'&endDateTime='$END'"Common Patterns
Extract ID for Chaining
# Get ID and remove quotes
WS_ID=$(fab get "ws.Workspace" -q "id" | tr -d '"')
MODEL_ID=$(fab get "ws.Workspace/Model.SemanticModel" -q "id" | tr -d '"')
# Use in API call
fab api -A powerbi "groups/$WS_ID/datasets/$MODEL_ID/refreshes" -X post -i '{"type":"Full"}'Pagination
# APIs with $top often have pagination
# Check for @odata.nextLink in response
fab api -A powerbi 'admin/groups?$top=100' -q "@odata.nextLink"
# Use returned URL for next pageError Handling
# Check status_code in response
# 200 = success
# 400 = bad request (check parameters)
# 401 = unauthorized (re-authenticate)
# 403 = forbidden (insufficient permissions)
# 404 = not foundAPI Audiences
| Audience | Flag | Base URL | Use Case |
|---|---|---|---|
| Fabric | (default) | api.fabric.microsoft.com | Fabric items, workspaces, admin |
| Power BI | -A powerbi | api.powerbi.com | Reports, datasets, gateways, pipelines |
Most admin operations work with both APIs but return different formats.
Notebook Operations
Comprehensive guide for working with Fabric notebooks using the Fabric CLI.
Overview
Fabric notebooks are interactive documents for data engineering, data science, and analytics. They can be executed, scheduled, and managed via the CLI.
Getting Notebook Information
Basic Notebook Info
# Check if notebook exists
fab exists "Production.Workspace/ETL Pipeline.Notebook"
# Get notebook properties
fab get "Production.Workspace/ETL Pipeline.Notebook"
# Get with verbose details
fab get "Production.Workspace/ETL Pipeline.Notebook" -v
# Get only notebook ID
fab get "Production.Workspace/ETL Pipeline.Notebook" -q "id"Get Notebook Definition
# Get full notebook definition
fab get "Production.Workspace/ETL Pipeline.Notebook" -q "definition"
# Save definition to file
fab get "Production.Workspace/ETL Pipeline.Notebook" -q "definition" -o /tmp/notebook-def.json
# Get notebook content (cells)
fab get "Production.Workspace/ETL Pipeline.Notebook" -q "definition.parts[?path=='notebook-content.py'].payload | [0]"Exporting Notebooks
Export as IPYNB
# Export notebook
fab export "Production.Workspace/ETL Pipeline.Notebook" -o /tmp/notebooks
# This creates:
# /tmp/notebooks/ETL Pipeline.Notebook/
# ├── notebook-content.py (or .ipynb)
# └── metadata filesExport All Notebooks from Workspace
# Export all notebooks
WS_ID=$(fab get "Production.Workspace" -q "id")
NOTEBOOKS=$(fab api "workspaces/$WS_ID/items" -q "value[?type=='Notebook'].displayName")
for NOTEBOOK in $NOTEBOOKS; do
fab export "Production.Workspace/$NOTEBOOK.Notebook" -o /tmp/notebooks
doneImporting Notebooks
Import from Local
# Import notebook from .ipynb format (default)
fab import "Production.Workspace/New ETL.Notebook" -i /tmp/notebooks/ETL\ Pipeline.Notebook
# Import from .py format
fab import "Production.Workspace/Script.Notebook" -i /tmp/script.py --format pyCopy Between Workspaces
# Copy notebook
fab cp "Dev.Workspace/ETL.Notebook" "Production.Workspace"
# Copy with new name
fab cp "Dev.Workspace/ETL.Notebook" "Production.Workspace/Prod ETL.Notebook"Creating Notebooks
Create Blank Notebook
# Get workspace ID first
fab get "Production.Workspace" -q "id"
# Create via API
fab api -X post "workspaces/<workspace-id>/notebooks" -i '{"displayName": "New Data Processing"}'Create and Configure Query Notebook
Use this workflow to create a notebook for querying lakehouse tables with Spark SQL.
Step 1: Create the notebook
# Get workspace ID
fab get "Sales.Workspace" -q "id"
# Returns: 4caf7825-81ac-4c94-9e46-306b4c20a4d5
# Create notebook
fab api -X post "workspaces/4caf7825-81ac-4c94-9e46-306b4c20a4d5/notebooks" -i '{"displayName": "Data Query"}'
# Returns notebook ID: 97bbd18d-c293-46b8-8536-82fb8bc9bd58Step 2: Get lakehouse ID (required for notebook metadata)
fab get "Sales.Workspace/SalesLH.Lakehouse" -q "id"
# Returns: ddbcc575-805b-4922-84db-ca451b318755Step 3: Create notebook code in Fabric format
cat > /tmp/notebook.py <<'EOF'
# Fabric notebook source
# METADATA ********************
# META {
# META "kernel_info": {
# META "name": "synapse_pyspark"
# META },
# META "dependencies": {
# META "lakehouse": {
# META "default_lakehouse": "ddbcc575-805b-4922-84db-ca451b318755",
# META "default_lakehouse_name": "SalesLH",
# META "default_lakehouse_workspace_id": "4caf7825-81ac-4c94-9e46-306b4c20a4d5"
# META }
# META }
# META }
# CELL ********************
# Query lakehouse table
df = spark.sql("""
SELECT
date_key,
COUNT(*) as num_records
FROM gold.sets
GROUP BY date_key
ORDER BY date_key DESC
LIMIT 10
""")
# IMPORTANT: Convert to pandas and print to capture output
# display(df) will NOT show results via API
pandas_df = df.toPandas()
print(pandas_df)
print(f"\nLatest date: {pandas_df.iloc[0]['date_key']}")
EOFStep 4: Base64 encode and create update definition
base64 -i /tmp/notebook.py > /tmp/notebook-b64.txt
cat > /tmp/update.json <<EOF
{
"definition": {
"parts": [
{
"path": "notebook-content.py",
"payload": "$(cat /tmp/notebook-b64.txt)",
"payloadType": "InlineBase64"
}
]
}
}
EOFStep 5: Update notebook with code
fab api -X post "workspaces/4caf7825-81ac-4c94-9e46-306b4c20a4d5/notebooks/97bbd18d-c293-46b8-8536-82fb8bc9bd58/updateDefinition" -i /tmp/update.json --show_headers
# Returns operation ID in Location headerStep 6: Check update completed
fab api "operations/<operation-id>"
# Wait for status: "Succeeded"Step 7: Run the notebook
fab job start "Sales.Workspace/Data Query.Notebook"
# Returns job instance IDStep 8: Check execution status
fab job run-status "Sales.Workspace/Data Query.Notebook" --id <job-id>
# Wait for status: "Completed"Step 9: Get results (download from Fabric UI)
- Open notebook in Fabric UI after execution
- Print output will be visible in cell outputs
- Download .ipynb file to see printed results locally
Critical Requirements
1. File format: Must be notebook-content.py (NOT .ipynb) 2. Lakehouse ID: Must include default_lakehouse ID in metadata (not just name) 3. Spark session: Will be automatically available when lakehouse is attached 4. Capturing output: Use df.toPandas() and print() - display() won't show in API 5. Results location: Print output visible in UI and downloaded .ipynb, NOT in definition
Common Issues
NameError: name 'spark' is not defined- Lakehouse not attached (missing default_lakehouse ID)- Job "Completed" but no results - Used display() instead of print()
- Update fails - Used .ipynb path instead of .py
Create from Template
# Export template
fab export "Templates.Workspace/Template Notebook.Notebook" -o /tmp/templates
# Import as new notebook
fab import "Production.Workspace/Custom Notebook.Notebook" -i /tmp/templates/Template\ Notebook.NotebookRunning Notebooks
Run Synchronously (Wait for Completion)
# Run notebook and wait
fab job run "Production.Workspace/ETL Pipeline.Notebook"
# Run with timeout (seconds)
fab job run "Production.Workspace/Long Process.Notebook" --timeout 600Run with Parameters
# Run with basic parameters
fab job run "Production.Workspace/ETL Pipeline.Notebook" -P \
date:string=2024-01-01,\
batch_size:int=1000,\
debug_mode:bool=false,\
threshold:float=0.95
# Parameters must match types defined in notebook
# Supported types: string, int, float, boolRun with Spark Configuration
# Run with custom Spark settings
fab job run "Production.Workspace/Big Data Processing.Notebook" -C '{
"conf": {
"spark.executor.memory": "8g",
"spark.executor.cores": "4",
"spark.dynamicAllocation.enabled": "true"
},
"environment": {
"id": "<environment-id>",
"name": "Production Environment"
}
}'
# Run with default lakehouse
fab job run "Production.Workspace/Data Ingestion.Notebook" -C '{
"defaultLakehouse": {
"name": "MainLakehouse",
"id": "<lakehouse-id>",
"workspaceId": "<workspace-id>"
}
}'
# Run with workspace Spark pool
fab job run "Production.Workspace/Analytics.Notebook" -C '{
"useStarterPool": false,
"useWorkspacePool": "HighMemoryPool"
}'Run with Combined Parameters and Configuration
# Combine parameters and configuration
fab job run "Production.Workspace/ETL Pipeline.Notebook" \
-P date:string=2024-01-01,batch:int=500 \
-C '{
"defaultLakehouse": {"name": "StagingLH", "id": "<lakehouse-id>"},
"conf": {"spark.sql.shuffle.partitions": "200"}
}'Run Asynchronously
# Start notebook and return immediately
JOB_ID=$(fab job start "Production.Workspace/ETL Pipeline.Notebook" | grep -o '"id": "[^"]*"' | cut -d'"' -f4)
# Check status later
fab job run-status "Production.Workspace/ETL Pipeline.Notebook" --id "$JOB_ID"Monitoring Notebook Executions
Get Job Status
# Check specific job
fab job run-status "Production.Workspace/ETL Pipeline.Notebook" --id <job-id>
# Get detailed status via API
WS_ID=$(fab get "Production.Workspace" -q "id")
NOTEBOOK_ID=$(fab get "Production.Workspace/ETL Pipeline.Notebook" -q "id")
fab api "workspaces/$WS_ID/items/$NOTEBOOK_ID/jobs/instances/<job-id>"List Execution History
# List all job runs
fab job run-list "Production.Workspace/ETL Pipeline.Notebook"
# List only scheduled runs
fab job run-list "Production.Workspace/ETL Pipeline.Notebook" --schedule
# Get latest run status
fab job run-list "Production.Workspace/ETL Pipeline.Notebook" | head -n 1Cancel Running Job
fab job run-cancel "Production.Workspace/ETL Pipeline.Notebook" --id <job-id>Scheduling Notebooks
Create Cron Schedule
# Run every 30 minutes
fab job run-sch "Production.Workspace/ETL Pipeline.Notebook" \
--type cron \
--interval 30 \
--start 2024-11-15T00:00:00 \
--end 2025-12-31T23:59:00 \
--enableCreate Daily Schedule
# Run daily at 2 AM and 2 PM
fab job run-sch "Production.Workspace/ETL Pipeline.Notebook" \
--type daily \
--interval 02:00,14:00 \
--start 2024-11-15T00:00:00 \
--end 2025-12-31T23:59:00 \
--enableCreate Weekly Schedule
# Run Monday and Friday at 9 AM
fab job run-sch "Production.Workspace/Weekly Report.Notebook" \
--type weekly \
--interval 09:00 \
--days Monday,Friday \
--start 2024-11-15T00:00:00 \
--enableUpdate Schedule
# Modify existing schedule
fab job run-update "Production.Workspace/ETL Pipeline.Notebook" \
--id <schedule-id> \
--type daily \
--interval 03:00 \
--enable
# Disable schedule
fab job run-update "Production.Workspace/ETL Pipeline.Notebook" \
--id <schedule-id> \
--disableNotebook Configuration
Set Default Lakehouse
# Via notebook properties
fab set "Production.Workspace/ETL.Notebook" -q lakehouse -i '{
"known_lakehouses": [{"id": "<lakehouse-id>"}],
"default_lakehouse": "<lakehouse-id>",
"default_lakehouse_name": "MainLakehouse",
"default_lakehouse_workspace_id": "<workspace-id>"
}'Set Default Environment
fab set "Production.Workspace/ETL.Notebook" -q environment -i '{
"environmentId": "<environment-id>",
"workspaceId": "<workspace-id>"
}'Set Default Warehouse
fab set "Production.Workspace/Analytics.Notebook" -q warehouse -i '{
"known_warehouses": [{"id": "<warehouse-id>", "type": "Datawarehouse"}],
"default_warehouse": "<warehouse-id>"
}'Updating Notebooks
Update Display Name
fab set "Production.Workspace/ETL.Notebook" -q displayName -i "ETL Pipeline v2"Update Description
fab set "Production.Workspace/ETL.Notebook" -q description -i "Daily ETL pipeline for sales data ingestion and transformation"Deleting Notebooks
# Delete with confirmation (interactive)
fab rm "Dev.Workspace/Old Notebook.Notebook"
# Force delete without confirmation
fab rm "Dev.Workspace/Old Notebook.Notebook" -fAdvanced Workflows
Parameterized Notebook Execution
# Create parametrized notebook with cell tagged as "parameters"
# In notebook, create cell:
date = "2024-01-01" # default
batch_size = 1000 # default
debug = False # default
# Execute with different parameters
fab job run "Production.Workspace/Parameterized.Notebook" -P \
date:string=2024-02-15,\
batch_size:int=2000,\
debug:bool=trueNotebook Orchestration Pipeline
#!/bin/bash
WORKSPACE="Production.Workspace"
DATE=$(date +%Y-%m-%d)
# 1. Run ingestion notebook
echo "Starting data ingestion..."
fab job run "$WORKSPACE/1_Ingest_Data.Notebook" -P date:string=$DATE
# 2. Run transformation notebook
echo "Running transformations..."
fab job run "$WORKSPACE/2_Transform_Data.Notebook" -P date:string=$DATE
# 3. Run analytics notebook
echo "Generating analytics..."
fab job run "$WORKSPACE/3_Analytics.Notebook" -P date:string=$DATE
# 4. Run reporting notebook
echo "Creating reports..."
fab job run "$WORKSPACE/4_Reports.Notebook" -P date:string=$DATE
echo "Pipeline completed for $DATE"Monitoring Long-Running Notebook
#!/bin/bash
NOTEBOOK="Production.Workspace/Long Process.Notebook"
# Start job
JOB_ID=$(fab job start "$NOTEBOOK" -P date:string=$(date +%Y-%m-%d) | \
grep -o '"id": "[^"]*"' | head -1 | cut -d'"' -f4)
echo "Started job: $JOB_ID"
# Poll status every 30 seconds
while true; do
STATUS=$(fab job run-status "$NOTEBOOK" --id "$JOB_ID" | \
grep -o '"status": "[^"]*"' | cut -d'"' -f4)
echo "[$(date +%H:%M:%S)] Status: $STATUS"
if [[ "$STATUS" == "Completed" ]] || [[ "$STATUS" == "Failed" ]]; then
break
fi
sleep 30
done
if [[ "$STATUS" == "Completed" ]]; then
echo "Job completed successfully"
exit 0
else
echo "Job failed"
exit 1
fiConditional Notebook Execution
#!/bin/bash
WORKSPACE="Production.Workspace"
# Check if data is ready
DATA_READY=$(fab api "workspaces/<ws-id>/lakehouses/<lh-id>/Files/ready.flag" 2>&1 | grep -c "200")
if [ "$DATA_READY" -eq 1 ]; then
echo "Data ready, running notebook..."
fab job run "$WORKSPACE/Process Data.Notebook" -P date:string=$(date +%Y-%m-%d)
else
echo "Data not ready, skipping execution"
fiNotebook Definition Structure
Notebook definition contains:
NotebookName.Notebook/ ├── .platform # Git integration metadata ├── notebook-content.py # Python code (or .ipynb format) └── metadata.json # Notebook metadata
Query Notebook Content
NOTEBOOK="Production.Workspace/ETL.Notebook"
# Get Python code content
fab get "$NOTEBOOK" -q "definition.parts[?path=='notebook-content.py'].payload | [0]" | base64 -d
# Get metadata
fab get "$NOTEBOOK" -q "definition.parts[?path=='metadata.json'].payload | [0]" | base64 -d | jq .Troubleshooting
Notebook Execution Failures
# Check recent execution
fab job run-list "Production.Workspace/ETL.Notebook" | head -n 5
# Get detailed error
fab job run-status "Production.Workspace/ETL.Notebook" --id <job-id> -q "error"
# Common issues:
# - Lakehouse not attached
# - Invalid parameters
# - Spark configuration errors
# - Missing dependenciesParameter Type Mismatches
# Parameters must match expected types
# ❌ Wrong: -P count:string=100 (should be int)
# ✅ Right: -P count:int=100
# Check notebook definition for parameter types
fab get "Production.Workspace/ETL.Notebook" -q "definition.parts[?path=='notebook-content.py']"Lakehouse Access Issues
# Verify lakehouse exists and is accessible
fab exists "Production.Workspace/MainLakehouse.Lakehouse"
# Check notebook's lakehouse configuration
fab get "Production.Workspace/ETL.Notebook" -q "properties.lakehouse"
# Re-attach lakehouse
fab set "Production.Workspace/ETL.Notebook" -q lakehouse -i '{
"known_lakehouses": [{"id": "<lakehouse-id>"}],
"default_lakehouse": "<lakehouse-id>",
"default_lakehouse_name": "MainLakehouse",
"default_lakehouse_workspace_id": "<workspace-id>"
}'Performance Tips
1. Use workspace pools: Faster startup than starter pool 2. Cache data in lakehouses: Avoid re-fetching data 3. Parameterize notebooks: Reuse logic with different inputs 4. Monitor execution time: Set appropriate timeouts 5. Use async execution: Don't block on long-running notebooks 6. Optimize Spark config: Tune for specific workloads
Best Practices
1. Tag parameter cells: Use "parameters" tag for injected params 2. Handle failures gracefully: Add error handling and logging 3. Version control notebooks: Export and commit to Git 4. Use descriptive names: Clear naming for scheduled jobs 5. Document parameters: Add comments explaining expected inputs 6. Test locally first: Validate in development workspace 7. Monitor schedules: Review execution history regularly 8. Clean up old notebooks: Remove unused notebooks
Security Considerations
1. Credential management: Use Key Vault for secrets 2. Workspace permissions: Control who can execute notebooks 3. Parameter validation: Sanitize inputs in notebook code 4. Data access: Respect lakehouse/warehouse permissions 5. Logging: Don't log sensitive information
Related Scripts
scripts/run_notebook_pipeline.py- Orchestrate multiple notebooksscripts/monitor_notebook.py- Monitor long-running executionsscripts/export_notebook.py- Export with validationscripts/schedule_notebook.py- Simplified scheduling interface
Querying Data
Query a Semantic Model (DAX)
# 1. Get workspace and model IDs
fab get "ws.Workspace" -q "id"
fab get "ws.Workspace/Model.SemanticModel" -q "id"
# 2. Execute DAX query
fab api -A powerbi "groups/<ws-id>/datasets/<model-id>/executeQueries" \
-X post -i '{"queries":[{"query":"EVALUATE TOPN(10, '\''TableName'\'')"}]}'Or use the helper script:
python3 scripts/execute_dax.py "ws.Workspace/Model.SemanticModel" -q "EVALUATE TOPN(10, 'Table')"Query a Lakehouse Table
Lakehouse tables cannot be queried directly via API. Create a Direct Lake semantic model first.
# 1. Create Direct Lake model from lakehouse table
python3 scripts/create_direct_lake_model.py \
"src.Workspace/LH.Lakehouse" \
"dest.Workspace/Model.SemanticModel" \
-t schema.table
# 2. Query via DAX
python3 scripts/execute_dax.py "dest.Workspace/Model.SemanticModel" -q "EVALUATE TOPN(10, 'table')"
# 3. (Optional) Delete temporary model
fab rm "dest.Workspace/Model.SemanticModel" -fGet Lakehouse SQL Endpoint
For external SQL clients:
fab get "ws.Workspace/LH.Lakehouse" -q "properties.sqlEndpointProperties"Returns connectionString and id for SQL connections.
Fabric CLI Quick Start Guide
Real working examples using Fabric workspaces and items. These commands are ready to copy-paste and modify for your own workspaces.
Finding Items
List Workspaces
# List all workspaces
fab ls
# List with details (shows IDs, types, etc.)
fab ls -l
# Find specific workspace
fab ls | grep "Sales"List Items in Workspace
# List all items in workspace
fab ls "Sales.Workspace"
# List with details (shows IDs, modification dates)
fab ls "Sales.Workspace" -l
# Filter by type
fab ls "Sales.Workspace" | grep "Notebook"
fab ls "Sales.Workspace" | grep "SemanticModel"
fab ls "Sales.Workspace" | grep "Lakehouse"Check if Item Exists
# Check workspace exists
fab exists "Sales.Workspace"
# Check specific item exists
fab exists "Sales.Workspace/Sales Model.SemanticModel"
fab exists "Sales.Workspace/SalesLH.Lakehouse"
fab exists "Sales.Workspace/ETL - Extract.Notebook"Get Item Details
# Get basic properties
fab get "Sales.Workspace/Sales Model.SemanticModel"
# Get all properties (verbose)
fab get "Sales.Workspace/Sales Model.SemanticModel" -v
# Get specific property (workspace ID)
fab get "Sales.Workspace" -q "id"
# Get specific property (model ID)
fab get "Sales.Workspace/Sales Model.SemanticModel" -q "id"
# Get display name
fab get "Sales.Workspace/Sales Model.SemanticModel" -q "displayName"Working with Semantic Models
Get Model Information
# Get model definition (full TMDL structure)
fab get "Sales.Workspace/Sales Model.SemanticModel" -q "definition"
# Save definition to file
fab get "Sales.Workspace/Sales Model.SemanticModel" -q "definition" > sales-model-definition.json
# Get model creation date
fab get "Sales.Workspace/Sales Model.SemanticModel" -q "properties.createdDateTime"
# Get model type (DirectLake, Import, etc.)
fab get "Sales.Workspace/Sales Model.SemanticModel" -q "properties.mode"Check Refresh Status
# First, get the workspace ID
fab get "Sales.Workspace" -q "id"
# Returns: a1b2c3d4-e5f6-7890-abcd-ef1234567890
# Then get the model ID
fab get "Sales.Workspace/Sales Model.SemanticModel" -q "id"
# Returns: 12345678-abcd-ef12-3456-789abcdef012
# Now use those IDs to get latest refresh (put $top in the URL)
fab api -A powerbi "groups/a1b2c3d4-e5f6-7890-abcd-ef1234567890/datasets/12345678-abcd-ef12-3456-789abcdef012/refreshes?\$top=1"
# Get full refresh history
fab api -A powerbi "groups/a1b2c3d4-e5f6-7890-abcd-ef1234567890/datasets/12345678-abcd-ef12-3456-789abcdef012/refreshes"Query Model with DAX
# First, get the model definition to see table/column names
fab get "Sales.Workspace/Sales Model.SemanticModel" -q "definition"
# Get the workspace and model IDs
fab get "Sales.Workspace" -q "id"
fab get "Sales.Workspace/Sales Model.SemanticModel" -q "id"
# Execute DAX query (using proper table qualification)
fab api -A powerbi "groups/a1b2c3d4-e5f6-7890-abcd-ef1234567890/datasets/12345678-abcd-ef12-3456-789abcdef012/executeQueries" -X post -i '{"queries":[{"query":"EVALUATE TOPN(1, '\''Orders'\'', '\''Orders'\''[OrderDate], DESC)"}],"serializerSettings":{"includeNulls":true}}'
# Query top 5 records from a table
fab api -A powerbi "groups/a1b2c3d4-e5f6-7890-abcd-ef1234567890/datasets/12345678-abcd-ef12-3456-789abcdef012/executeQueries" -X post -i '{"queries":[{"query":"EVALUATE TOPN(5, '\''Orders'\'')"}],"serializerSettings":{"includeNulls":true}}'Trigger Model Refresh
# Get workspace and model IDs
fab get "Sales.Workspace" -q "id"
fab get "Sales.Workspace/Sales Model.SemanticModel" -q "id"
# Trigger full refresh
fab api -A powerbi "groups/a1b2c3d4-e5f6-7890-abcd-ef1234567890/datasets/12345678-abcd-ef12-3456-789abcdef012/refreshes" -X post -i '{"type": "Full", "commitMode": "Transactional"}'
# Monitor refresh status
fab api -A powerbi "groups/a1b2c3d4-e5f6-7890-abcd-ef1234567890/datasets/12345678-abcd-ef12-3456-789abcdef012/refreshes?\$top=1"Working with Notebooks
List Notebooks
# List all notebooks in workspace
fab ls "Sales.Workspace" | grep "Notebook"
# Get specific notebook details
fab get "Sales.Workspace/ETL - Extract.Notebook"
# Get notebook ID
fab get "Sales.Workspace/ETL - Extract.Notebook" -q "id"Run Notebook
# Run notebook synchronously (wait for completion)
fab job run "Sales.Workspace/ETL - Extract.Notebook"
# Run with timeout (300 seconds = 5 minutes)
fab job run "Sales.Workspace/ETL - Extract.Notebook" --timeout 300
# Run with parameters
fab job run "Sales.Workspace/ETL - Extract.Notebook" -P \
date:string=2025-10-17,\
debug:bool=trueRun Notebook Asynchronously
# Start notebook and return immediately
fab job start "Sales.Workspace/ETL - Extract.Notebook"
# Check execution history
fab job run-list "Sales.Workspace/ETL - Extract.Notebook"
# Check specific job status (replace <job-id> with actual ID)
fab job run-status "Sales.Workspace/ETL - Extract.Notebook" --id <job-id>Get Notebook Definition
# Get full notebook definition
fab get "Sales.Workspace/ETL - Extract.Notebook" -q "definition"
# Save to file
fab get "Sales.Workspace/ETL - Extract.Notebook" -q "definition" > etl-extract-notebook.json
# Get notebook code content
fab get "Sales.Workspace/ETL - Extract.Notebook" -q "definition.parts[?path=='notebook-content.py'].payload | [0]" | base64 -dWorking with Lakehouses
Browse Lakehouse
# List lakehouse contents
fab ls "Sales.Workspace/SalesLH.Lakehouse"
# List Files directory
fab ls "Sales.Workspace/SalesLH.Lakehouse/Files"
# List specific folder in Files
fab ls "Sales.Workspace/SalesLH.Lakehouse/Files/2025/10"
# List Tables
fab ls "Sales.Workspace/SalesLH.Lakehouse/Tables"
# List with details (shows sizes, modified dates)
fab ls "Sales.Workspace/SalesLH.Lakehouse/Tables" -l
# List specific schema tables
fab ls "Sales.Workspace/SalesLH.Lakehouse/Tables/bronze"
fab ls "Sales.Workspace/SalesLH.Lakehouse/Tables/gold"Get Table Schema
# View table schema
fab table schema "Sales.Workspace/SalesLH.Lakehouse/Tables/bronze/raw_orders"
fab table schema "Sales.Workspace/SalesLH.Lakehouse/Tables/gold/orders"
# Save schema to file
fab table schema "Sales.Workspace/SalesLH.Lakehouse/Tables/gold/orders" > orders-schema.jsonCheck Table Last Modified
# List tables with modification times
fab ls "Sales.Workspace/SalesLH.Lakehouse/Tables/gold" -l
# Get specific table details
fab get "Sales.Workspace/SalesLH.Lakehouse/Tables/gold/orders"Working with Reports
List Reports
# List all reports
fab ls "Sales.Workspace" | grep "Report"
# Get report details
fab get "Sales.Workspace/Sales Dashboard.Report"
# Get report ID
fab get "Sales.Workspace/Sales Dashboard.Report" -q "id"Export Report Definition
# Get report definition as JSON
fab get "Sales.Workspace/Sales Dashboard.Report" -q "definition" > sales-report.json
# Export report to local directory (creates PBIR structure)
fab export "Sales.Workspace/Sales Dashboard.Report" -o ./reports-backup -fGet Report Metadata
# Get connected semantic model ID
fab get "Sales.Workspace/Sales Dashboard.Report" -q "properties.datasetId"
# Get report connection string
fab get "Sales.Workspace/Sales Dashboard.Report" -q "definition.parts[?path=='definition.pbir'].payload.datasetReference"Download and Re-upload Workflows
Backup Semantic Model
# 1. Get model definition
fab get "Sales.Workspace/Sales Model.SemanticModel" -q "definition" > backup-sales-model-$(date +%Y%m%d).json
# 2. Get model metadata
fab get "Sales.Workspace/Sales Model.SemanticModel" > backup-sales-model-metadata-$(date +%Y%m%d).jsonExport and Import Notebook
# Export notebook
fab export "Sales.Workspace/ETL - Extract.Notebook" -o ./notebooks-backup
# Import to another workspace (or same workspace with different name)
fab import "Dev.Workspace/ETL Extract Copy.Notebook" -i ./notebooks-backup/ETL\ -\ Extract.NotebookCopy Items Between Workspaces
# Copy semantic model
fab cp "Sales.Workspace/Sales Model.SemanticModel" "Dev.Workspace"
# Copy with new name
fab cp "Sales.Workspace/Sales Model.SemanticModel" "Dev.Workspace/Sales Model Test.SemanticModel"
# Copy notebook
fab cp "Sales.Workspace/ETL - Extract.Notebook" "Dev.Workspace"
# Copy report
fab cp "Sales.Workspace/Sales Dashboard.Report" "Dev.Workspace"Combined Workflows
Complete Model Status Check
# Check last refresh
fab api -A powerbi "groups/a1b2c3d4-e5f6-7890-abcd-ef1234567890/datasets/12345678-abcd-ef12-3456-789abcdef012/refreshes?\$top=1"
# Check latest data in model
fab api -A powerbi "groups/a1b2c3d4-e5f6-7890-abcd-ef1234567890/datasets/12345678-abcd-ef12-3456-789abcdef012/executeQueries" -X post -i '{"queries":[{"query":"EVALUATE TOPN(1, '\''Orders'\'', '\''Orders'\''[OrderDate], DESC)"}],"serializerSettings":{"includeNulls":true}}'
# Check lakehouse data freshness
fab ls "Sales.Workspace/SalesLH.Lakehouse/Tables/gold/orders" -lCheck All Notebooks in Workspace
# List all notebooks
fab ls "Sales.Workspace" | grep Notebook
# Check execution history for each
fab job run-list "Sales.Workspace/ETL - Extract.Notebook"
fab job run-list "Sales.Workspace/ETL - Transform.Notebook"Monitor Lakehouse Data Freshness
# Check gold layer tables
fab ls "Sales.Workspace/SalesLH.Lakehouse/Tables/gold" -l
# Check bronze layer tables
fab ls "Sales.Workspace/SalesLH.Lakehouse/Tables/bronze" -l
# Check latest files
fab ls "Sales.Workspace/SalesLH.Lakehouse/Files/2025/10" -lTips and Tricks
Get IDs for API Calls
# Get workspace ID
fab get "Sales.Workspace" -q "id"
# Get model ID
fab get "Sales.Workspace/Sales Model.SemanticModel" -q "id"
# Get lakehouse ID
fab get "Sales.Workspace/SalesLH.Lakehouse" -q "id"
# Then use the IDs directly in API calls
fab api "workspaces/a1b2c3d4-e5f6-7890-abcd-ef1234567890/items"
fab api -A powerbi "groups/a1b2c3d4-e5f6-7890-abcd-ef1234567890/datasets/12345678-abcd-ef12-3456-789abcdef012/refreshes"Pipe to jq for Pretty JSON
# Pretty print JSON output
fab get "Sales.Workspace/Sales Model.SemanticModel" | jq .
# Extract specific fields
fab get "Sales.Workspace/Sales Model.SemanticModel" | jq '{id: .id, name: .displayName, created: .properties.createdDateTime}'
# Get workspace ID first, then filter arrays
fab get "Sales.Workspace" -q "id"
fab api "workspaces/a1b2c3d4-e5f6-7890-abcd-ef1234567890/items" | jq '.value[] | select(.type=="Notebook") | .displayName'Use with grep for Filtering
# Find items by pattern
fab ls "Sales.Workspace" | grep -i "etl"
fab ls "Sales.Workspace" | grep -i "sales"
# Count items by type
fab ls "Sales.Workspace" | grep -c "Notebook"
fab ls "Sales.Workspace" | grep -c "SemanticModel"Create Aliases for Common Commands
# Add to ~/.bashrc or ~/.zshrc
alias sales-ls='fab ls "Sales.Workspace"'
alias sales-notebooks='fab ls "Sales.Workspace" | grep Notebook'
alias sales-refresh='fab api -A powerbi "groups/<ws-id>/datasets/<model-id>/refreshes?\$top=1"'
# Then use:
sales-ls
sales-notebooks
sales-refreshCommon Patterns
Get All Items of a Type
# Get workspace ID first
fab get "Sales.Workspace" -q "id"
# Get all notebooks
fab api "workspaces/a1b2c3d4-e5f6-7890-abcd-ef1234567890/items" -q "value[?type=='Notebook']"
# Get all semantic models
fab api "workspaces/a1b2c3d4-e5f6-7890-abcd-ef1234567890/items" -q "value[?type=='SemanticModel']"
# Get all lakehouses
fab api "workspaces/a1b2c3d4-e5f6-7890-abcd-ef1234567890/items" -q "value[?type=='Lakehouse']"
# Get all reports
fab api "workspaces/a1b2c3d4-e5f6-7890-abcd-ef1234567890/items" -q "value[?type=='Report']"Export Entire Workspace
# Export all items in workspace
fab export "Sales.Workspace" -o ./sales-workspace-backup -a
# This creates a full backup with all itemsFind Items by Name Pattern
# Get workspace ID first
fab get "Sales.Workspace" -q "id"
# Find items with "ETL" in name
fab api "workspaces/a1b2c3d4-e5f6-7890-abcd-ef1234567890/items" -q "value[?contains(displayName, 'ETL')]"
# Find items with "Sales" in name
fab api "workspaces/a1b2c3d4-e5f6-7890-abcd-ef1234567890/items" -q "value[?contains(displayName, 'Sales')]"Next Steps
- See semantic-models.md for advanced model operations
- See notebooks.md for notebook scheduling and orchestration
- See reports.md for report deployment workflows
- See scripts/README.md for helper scripts
Fabric CLI Command Reference
Comprehensive reference for Microsoft Fabric CLI commands, flags, and patterns.
Table of Contents
Item Types
All 35 supported item types:
| Extension | Description |
|---|---|
.Workspace | Workspaces (containers) |
.SemanticModel | Power BI datasets/semantic models |
.Report | Power BI reports |
.Dashboard | Power BI dashboards |
.PaginatedReport | Paginated reports |
.Notebook | Fabric notebooks |
.DataPipeline | Data pipelines |
.SparkJobDefinition | Spark job definitions |
.Lakehouse | Lakehouses |
.Warehouse | Warehouses |
.SQLDatabase | SQL databases |
.SQLEndpoint | SQL endpoints |
.MirroredDatabase | Mirrored databases |
.MirroredWarehouse | Mirrored warehouses |
.KQLDatabase | KQL databases |
.KQLDashboard | KQL dashboards |
.KQLQueryset | KQL querysets |
.Eventhouse | Eventhouses |
.Eventstream | Event streams |
.Datamart | Datamarts |
.Environment | Spark environments |
.Reflex | Reflex items |
.MLModel | ML models |
.MLExperiment | ML experiments |
.GraphQLApi | GraphQL APIs |
.MountedDataFactory | Mounted data factories |
.CopyJob | Copy jobs |
.VariableLibrary | Variable libraries |
.SparkPool | Spark pools |
.ManagedIdentity | Managed identities |
.ManagedPrivateEndpoint | Managed private endpoints |
.ExternalDataShare | External data shares |
.Folder | Folders |
.Capacity | Capacities |
.Personal | Personal workspaces |
File System Commands
ls (dir) - List Resources
Syntax
fab ls [path] [-l] [-a]Flags
-l- Long format (detailed)-a- Show hidden items
Examples
# List workspaces
fab ls
# List items in workspace with details
fab ls "Production.Workspace" -l
# Show hidden items (capacities, connections, domains, gateways)
fab ls -la
# List lakehouse contents
fab ls "Data.Workspace/LH.Lakehouse"
fab ls "Data.Workspace/LH.Lakehouse/Files"
fab ls "Data.Workspace/LH.Lakehouse/Tables/dbo"cd - Change Directory
Syntax
fab cd <path>Examples
# Navigate to workspace
fab cd "Production.Workspace"
# Navigate to item
fab cd "/Analytics.Workspace/Sales.SemanticModel"
# Relative navigation
fab cd "../Dev.Workspace"
# Personal workspace
fab cd ~pwd - Print Working Directory
Syntax
fab pwdexists - Check Existence
Syntax
fab exists <path>Returns
* true or * false
Examples
fab exists "Production.Workspace"
fab exists "Production.Workspace/Sales.SemanticModel"get - Get Resource Details
Syntax
fab get <path> [-v] [-q <jmespath>] [-o <output>]Flags
-v, --verbose- Show all properties-q, --query- JMESPath query-o, --output- Save to file
Examples
# Get workspace
fab get "Production.Workspace"
# Get item with all properties
fab get "Production.Workspace/Sales.Report" -v
# Query specific property
fab get "Production.Workspace" -q "id"
fab get "Production.Workspace/Sales.SemanticModel" -q "definition.parts[0]"
# Save to file
fab get "Production.Workspace/Sales.SemanticModel" -o /tmp/model.jsonset - Set Resource Properties
Syntax
fab set <path> -q <property_path> -i <value>Flags
-q, --query- Property path (JMESPath-style)-i, --input- New value (string or JSON)
Examples
# Update display name
fab set "Production.Workspace/Item.Notebook" -q displayName -i "New Name"
# Update description
fab set "Production.Workspace" -q description -i "Production environment"
# Update Spark runtime
fab set "Production.Workspace" -q sparkSettings.environment.runtimeVersion -i 1.2
# Assign Spark pool
fab set "Production.Workspace" -q sparkSettings.pool.defaultPool -i '{"name": "Starter Pool", "type": "Workspace"}'
# Rebind report to model
fab set "Production.Workspace/Report.Report" -q semanticModelId -i "<model-id>"mkdir (create) - Create Resources
Syntax
fab mkdir <path> [-P <param=value>]Flags
-P, --params- Parameters (key=value format)
Examples
# Create workspace
fab mkdir "NewWorkspace.Workspace"
fab mkdir "NewWorkspace.Workspace" -P capacityname=MyCapacity
fab mkdir "NewWorkspace.Workspace" -P capacityname=none
# Create items
fab mkdir "Production.Workspace/NewLakehouse.Lakehouse"
fab mkdir "Production.Workspace/Notebook.Notebook"
# Create with parameters
fab mkdir "Production.Workspace/LH.Lakehouse" -P enableSchemas=true
fab mkdir "Production.Workspace/DW.Warehouse" -P enableCaseInsensitive=true
# Check supported parameters
fab mkdir "Item.Lakehouse" -Pcp (copy) - Copy Resources
Syntax
fab cp <source> <destination>Supported types
.Notebook, .SparkJobDefinition, .DataPipeline, .Report, .SemanticModel, .KQLDatabase, .KQLDashboard, .KQLQueryset, .Eventhouse, .Eventstream, .MirroredDatabase, .Reflex, .MountedDataFactory, .CopyJob, .VariableLibrary
Examples
# Copy item to workspace (keeps same name)
fab cp "Dev.Workspace/Pipeline.DataPipeline" "Production.Workspace"
# Copy with new name
fab cp "Dev.Workspace/Pipeline.DataPipeline" "Production.Workspace/ProdPipeline.DataPipeline"
# Copy to folder
fab cp "Dev.Workspace/Report.Report" "Production.Workspace/Reports.Folder"
# Copy files to/from lakehouse
fab cp ./local-data.csv "Data.Workspace/LH.Lakehouse/Files/data.csv"
fab cp "Data.Workspace/LH.Lakehouse/Files/data.csv" ~/Downloads/mv (move) - Move Resources
Syntax
fab mv <source> <destination>Examples
# Move item to workspace
fab mv "Dev.Workspace/Pipeline.DataPipeline" "Production.Workspace"
# Move with rename
fab mv "Dev.Workspace/Pipeline.DataPipeline" "Production.Workspace/NewPipeline.DataPipeline"
# Move to folder
fab mv "Dev.Workspace/Report.Report" "Production.Workspace/Archive.Folder"rm (del) - Delete Resources
Syntax
fab rm <path> [-f]Flags
-f, --force- Skip confirmation
Examples
# Delete with confirmation (interactive)
fab rm "Dev.Workspace/OldReport.Report"
# Force delete
fab rm "Dev.Workspace/OldLakehouse.Lakehouse" -f
# Delete workspace and all contents
fab rm "OldWorkspace.Workspace" -fexport - Export Item Definitions
Syntax
fab export <item_path> -o <output_path> [-a]Flags
-o, --output- Output directory (local or lakehouse Files)-a- Export all items (when exporting workspace)
Supported types
Same as cp command
Examples
# Export item to local
fab export "Production.Workspace/Sales.SemanticModel" -o /tmp/exports
# Export all workspace items
fab export "Production.Workspace" -o /tmp/backup -a
# Export to lakehouse
fab export "Production.Workspace/Pipeline.DataPipeline" -o "Data.Workspace/Archive.Lakehouse/Files/exports"import - Import Item Definitions
Syntax
fab import <item_path> -i <input_path> [--format <format>]Flags
-i, --input- Input directory or file--format- Format override (e.g.,pyfor notebooks)
Examples
# Import item from local
fab import "Production.Workspace/Pipeline.DataPipeline" -i /tmp/exports/Pipeline.DataPipeline
# Import notebook from Python file
fab import "Production.Workspace/ETL.Notebook" -i /tmp/etl_script.py --format py
# Import from lakehouse
fab import "Production.Workspace/Report.Report" -i "Data.Workspace/Archive.Lakehouse/Files/exports/Report.Report"open - Open in Browser
Syntax
fab open <path>Examples
fab open "Production.Workspace"
fab open "Production.Workspace/Sales.Report"ln (mklink) - Create Shortcuts
Syntax
fab ln <source> <destination>assign / unassign - Capacity Assignment
Syntax
fab assign <workspace> -P capacityId=<capacity-id>
fab unassign <workspace>start / stop - Start/Stop Resources
Syntax
fab start <path> [-f]
fab stop <path> [-f]Supported
.MirroredDatabase
Examples
fab start "Data.Workspace/Mirror.MirroredDatabase" -f
fab stop "Data.Workspace/Mirror.MirroredDatabase" -fAPI Commands
api - Make API Requests
Syntax
fab api <endpoint> [-A <audience>] [-X <method>] [-i <input>] [-q <query>] [-P <params>] [-H <headers>] [--show_headers]Flags
-A, --audience- API audience (fabric, powerbi, storage, azure)-X, --method- HTTP method (get, post, put, delete, patch)-i, --input- Request body (JSON string or file path)-q, --query- JMESPath query to filter response-P, --params- Query parameters (key=value format)-H, --headers- Additional headers (key=value format)--show_headers- Include response headers
Audiences
| Audience | Base URL | Use For |
|---|---|---|
fabric (default) | https://api.fabric.microsoft.com | Fabric REST API |
powerbi | https://api.powerbi.com | Power BI REST API, DAX queries |
storage | https://*.dfs.fabric.microsoft.com | OneLake Storage API |
azure | https://management.azure.com | Azure Resource Manager |
Examples
Fabric API
# GET requests
fab api workspaces
fab api "workspaces/<workspace-id>"
fab api "workspaces/<workspace-id>/items"
fab api workspaces -q "value[?type=='Workspace']"
# POST request with inline JSON
fab api -X post "workspaces/<workspace-id>/items" -i '{"displayName": "New Item", "type": "Lakehouse"}'
# POST with file
fab api -X post "workspaces/<workspace-id>/lakehouses" -i /tmp/config.json
# PUT to update
fab api -X put "workspaces/<workspace-id>/items/<item-id>" -i '{"displayName": "Updated"}'
# DELETE
fab api -X delete "workspaces/<workspace-id>/items/<item-id>"
# Update semantic model definition
fab api -X post "workspaces/<workspace-id>/semanticModels/<model-id>/updateDefinition" -i /tmp/definition.json --show_headersPower BI API
# List groups (workspaces)
fab api -A powerbi groups
# Get datasets in workspace
fab api -A powerbi "groups/<workspace-id>/datasets"
# Execute DAX query
fab api -A powerbi "datasets/<model-id>/executeQueries" -X post -i '{"queries": [{"query": "EVALUATE VALUES(Date[Year])"}]}'
# Refresh dataset
fab api -A powerbi "datasets/<model-id>/refreshes" -X post -i '{}'
# Get refresh history
fab api -A powerbi "datasets/<model-id>/refreshes"OneLake Storage API
# List files with parameters
fab api -A storage "WorkspaceName.Workspace/LH.Lakehouse/Files" -P resource=filesystem,recursive=false
# With query string
fab api -A storage "WorkspaceName/LH.Lakehouse/Files?resource=filesystem&recursive=false"Azure Resource Manager
# List Fabric capacities
fab api -A azure "subscriptions/<subscription-id>/providers/Microsoft.Fabric/capacities?api-version=2023-11-01"
# Get available SKUs
fab api -A azure "subscriptions/<subscription-id>/providers/Microsoft.Fabric/skus?api-version=2023-11-01"Job Commands
job run - Run Job Synchronously
Syntax
fab job run <item_path> [--timeout <seconds>] [-P <params>] [-C <config>] [-i <input>]Flags
--timeout- Timeout in seconds-P, --params- Job parameters (typed:name:type=value)-C, --config- Configuration JSON (file or inline)-i, --input- Raw JSON input (file or inline)
Supported items
.Notebook, .DataPipeline, .SparkJobDefinition, .Lakehouse (maintenance)
Parameter types
- Notebook:
string,int,float,bool - DataPipeline:
string,int,float,bool,object,array,secureString
Examples
# Run notebook
fab job run "Production.Workspace/ETL.Notebook"
# Run with timeout
fab job run "Production.Workspace/LongProcess.Notebook" --timeout 300
# Run with parameters
fab job run "Production.Workspace/ETL.Notebook" -P date:string=2024-01-01,batch_size:int=1000,debug:bool=false
# Run pipeline with complex parameters
fab job run "Production.Workspace/Pipeline.DataPipeline" -P 'config:object={"source":"s3","batch":100},ids:array=[1,2,3],secret:secureString=mysecret'
# Run with Spark configuration
fab job run "Production.Workspace/ETL.Notebook" -C '{"conf": {"spark.executor.memory": "8g"}, "environment": {"id": "<env-id>", "name": "ProdEnv"}}'
# Run with default lakehouse
fab job run "Production.Workspace/Process.Notebook" -C '{"defaultLakehouse": {"name": "MainLH", "id": "<lh-id>"}}'
# Run with workspace pool
fab job run "Production.Workspace/BigData.Notebook" -C '{"useStarterPool": false, "useWorkspacePool": "HighMemoryPool"}'
# Run with raw JSON
fab job run "Production.Workspace/ETL.Notebook" -i '{"parameters": {"date": {"type": "string", "value": "2024-01-01"}}, "configuration": {"conf": {"spark.conf1": "value"}}}'job start - Start Job Asynchronously
Syntax
fab job start <item_path> [-P <params>] [-C <config>] [-i <input>]Examples
# Start and return immediately
fab job start "Production.Workspace/ETL.Notebook"
# Start with parameters
fab job start "Production.Workspace/Pipeline.DataPipeline" -P source:string=salesdb,batch:int=500job run-list - List Job History
Syntax
fab job run-list <item_path> [--schedule]Flags
--schedule- Show only scheduled job runs
Examples
# List all job runs
fab job run-list "Production.Workspace/ETL.Notebook"
# List scheduled runs only
fab job run-list "Production.Workspace/ETL.Notebook" --schedulejob run-status - Get Job Status
Syntax
fab job run-status <item_path> --id <job_id> [--schedule]Flags
--id- Job or schedule ID--schedule- Check scheduled job status
Examples
# Check job instance status
fab job run-status "Production.Workspace/ETL.Notebook" --id <job-id>
# Check schedule status
fab job run-status "Production.Workspace/Pipeline.DataPipeline" --id <schedule-id> --schedulejob run-cancel - Cancel Job
Syntax
fab job run-cancel <item_path> --id <job_id>Examples
fab job run-cancel "Production.Workspace/ETL.Notebook" --id <job-id>job run-sch - Schedule Job
Syntax
fab job run-sch <item_path> --type <type> --interval <interval> [--days <days>] --start <datetime> [--end <datetime>] [--enable] [-i <json>]Flags
--type- Schedule type (cron, daily, weekly)--interval- Interval (minutes for cron, HH:MM for daily/weekly)--days- Days for weekly (Monday,Friday)--start- Start datetime (ISO 8601)--end- End datetime (ISO 8601)--enable- Enable schedule immediately-i, --input- Raw JSON schedule configuration
Examples
# Cron schedule (every 10 minutes)
fab job run-sch "Production.Workspace/Pipeline.DataPipeline" --type cron --interval 10 --start 2024-11-15T09:00:00 --end 2024-12-15T10:00:00 --enable
# Daily schedule
fab job run-sch "Production.Workspace/Pipeline.DataPipeline" --type daily --interval 10:00,16:00 --start 2024-11-15T09:00:00 --end 2024-12-16T10:00:00
# Weekly schedule
fab job run-sch "Production.Workspace/Pipeline.DataPipeline" --type weekly --interval 10:00,16:00 --days Monday,Friday --start 2024-11-15T09:00:00 --end 2024-12-16T10:00:00 --enable
# Custom JSON configuration
fab job run-sch "Production.Workspace/Pipeline.DataPipeline" -i '{"enabled": true, "configuration": {"startDateTime": "2024-04-28T00:00:00", "endDateTime": "2024-04-30T23:59:00", "localTimeZoneId": "Central Standard Time", "type": "Cron", "interval": 10}}'job run-update - Update Job Schedule
Syntax
fab job run-update <item_path> --id <schedule_id> [--type <type>] [--interval <interval>] [--enable] [--disable] [-i <json>]Examples
# Disable schedule
fab job run-update "Production.Workspace/Pipeline.DataPipeline" --id <schedule-id> --disable
# Update frequency
fab job run-update "Production.Workspace/Pipeline.DataPipeline" --id <schedule-id> --type cron --interval 5 --enable
# Update with JSON
fab job run-update "Production.Workspace/Pipeline.DataPipeline" --id <schedule-id> -i '{"enabled": false}'Table Commands
table schema - View Table Schema
Syntax
fab table schema <table_path>Supported items
.Lakehouse, .Warehouse, .MirroredDatabase, .SQLDatabase, .SemanticModel, .KQLDatabase
Examples
fab table schema "Data.Workspace/LH.Lakehouse/Tables/dbo/customers"
fab table schema "Analytics.Workspace/DW.Warehouse/Tables/sales/orders"table load - Load Data
Syntax
fab table load <table_path> --file <file_path> [--mode <mode>] [--format <format>] [--extension <ext>]Flags
--file- Source file or folder path (lakehouse Files location)--mode- Load mode (append, overwrite) - default: append--format- Format options (e.g.,format=csv,header=true,delimiter=;)--extension- File extension filter
Note
Not supported in schema-enabled lakehouses.
Examples
# Load CSV from folder
fab table load "Data.Workspace/LH.Lakehouse/Tables/customers" --file "Data.Workspace/LH.Lakehouse/Files/csv/customers"
# Load specific CSV with append mode
fab table load "Data.Workspace/LH.Lakehouse/Tables/sales" --file "Data.Workspace/LH.Lakehouse/Files/daily_sales.csv" --mode append
# Load with custom CSV format
fab table load "Data.Workspace/LH.Lakehouse/Tables/products" --file "Data.Workspace/LH.Lakehouse/Files/data" --format "format=csv,header=false,delimiter=;"
# Load Parquet files
fab table load "Data.Workspace/LH.Lakehouse/Tables/events" --file "Data.Workspace/LH.Lakehouse/Files/parquet/events" --format format=parquet --mode appendtable optimize - Optimize Table
Syntax
fab table optimize <table_path> [--vorder] [--zorder <columns>]Flags
--vorder- Enable V-Order optimization--zorder- Z-Order columns (comma-separated)
Note
Lakehouse only.
Examples
# Basic optimization
fab table optimize "Data.Workspace/LH.Lakehouse/Tables/transactions"
# V-Order optimization
fab table optimize "Data.Workspace/LH.Lakehouse/Tables/sales" --vorder
# V-Order + Z-Order
fab table optimize "Data.Workspace/LH.Lakehouse/Tables/customers" --vorder --zorder customer_id,region_idtable vacuum - Vacuum Table
Syntax
fab table vacuum <table_path> [--retain_n_hours <hours>]Flags
--retain_n_hours- Retention period in hours (default: 168 = 7 days)
Note
Lakehouse only.
Examples
# Vacuum with default retention (7 days)
fab table vacuum "Data.Workspace/LH.Lakehouse/Tables/transactions"
# Vacuum with custom retention (48 hours)
fab table vacuum "Data.Workspace/LH.Lakehouse/Tables/temp_data" --retain_n_hours 48Advanced Patterns
Batch Operations with Shell Scripts
#!/bin/bash
# Export all semantic models from workspace
WORKSPACE="Production.Workspace"
MODELS=$(fab api workspaces -q "value[?displayName=='Production'].id | [0]" | xargs -I {} fab api workspaces/{}/items -q "value[?type=='SemanticModel'].displayName")
for MODEL in $MODELS; do
fab export "$WORKSPACE/$MODEL.SemanticModel" -o /tmp/exports
doneDAX Query Workflow
# 1. Get model ID
MODEL_ID=$(fab get "Production.Workspace/Sales.SemanticModel" -q "id")
# 2. Execute DAX query
fab api -A powerbi "datasets/$MODEL_ID/executeQueries" -X post -i '{
"queries": [{
"query": "EVALUATE TOPN(10, Sales, Sales[Amount], DESC)"
}],
"serializerSettings": {
"includeNulls": false
}
}'
# 3. Execute multiple queries
fab api -A powerbi "datasets/$MODEL_ID/executeQueries" -X post -i '{
"queries": [
{"query": "EVALUATE VALUES(Date[Year])"},
{"query": "EVALUATE SUMMARIZE(Sales, Date[Year], \"Total\", SUM(Sales[Amount]))"}
]
}'Semantic Model Update Workflow
# 1. Get current definition
fab get "Production.Workspace/Sales.SemanticModel" -q definition -o /tmp/current-def.json
# 2. Modify definition (edit JSON file)
# ... edit /tmp/current-def.json ...
# 3. Get workspace and model IDs
WS_ID=$(fab get "Production.Workspace" -q "id")
MODEL_ID=$(fab get "Production.Workspace/Sales.SemanticModel" -q "id")
# 4. Prepare update request (wrap definition)
cat > /tmp/update-request.json <<EOF
{
"definition": $(cat /tmp/current-def.json)
}
EOF
# 5. Update definition
fab api -X post "workspaces/$WS_ID/semanticModels/$MODEL_ID/updateDefinition" -i /tmp/update-request.json --show_headers
# 6. Poll operation status (extract operation ID from Location header)
# Operation ID is in Location header: .../operations/{operation-id}
fab api "operations/<operation-id>"Environment Migration Script
#!/bin/bash
SOURCE_WS="Dev.Workspace"
TARGET_WS="Production.Workspace"
# Export all exportable items
fab export "$SOURCE_WS" -o /tmp/migration -a
# Import items to target workspace
for ITEM in /tmp/migration/*.Notebook; do
ITEM_NAME=$(basename "$ITEM")
fab import "$TARGET_WS/$ITEM_NAME" -i "$ITEM"
done
for ITEM in /tmp/migration/*.DataPipeline; do
ITEM_NAME=$(basename "$ITEM")
fab import "$TARGET_WS/$ITEM_NAME" -i "$ITEM"
doneJob Monitoring Loop
#!/bin/bash
# Start job
JOB_ID=$(fab job start "Production.Workspace/ETL.Notebook" | grep -o '"id": "[^"]*"' | cut -d'"' -f4)
# Poll status every 10 seconds
while true; do
STATUS=$(fab job run-status "Production.Workspace/ETL.Notebook" --id "$JOB_ID" -q "status")
echo "Job status: $STATUS"
if [[ "$STATUS" == "Completed" ]] || [[ "$STATUS" == "Failed" ]]; then
break
fi
sleep 10
done
echo "Job finished with status: $STATUS"Workspace Inventory
#!/bin/bash
# Get all workspaces and their item counts
WORKSPACES=$(fab api workspaces -q "value[].{name: displayName, id: id}")
echo "$WORKSPACES" | jq -r '.[] | [.name, .id] | @tsv' | while IFS=$'\t' read -r NAME ID; do
ITEM_COUNT=$(fab api "workspaces/$ID/items" -q "value | length")
echo "$NAME: $ITEM_COUNT items"
doneJMESPath Quick Reference
Common JMESPath patterns for -q flag:
# Get field
-q "id"
-q "displayName"
# Get nested field
-q "properties.sqlEndpointProperties"
-q "definition.parts[0]"
# Filter array
-q "value[?type=='Lakehouse']"
-q "value[?contains(name, 'prod')]"
-q "value[?starts_with(displayName, 'Test')]"
# Get first/last element
-q "value[0]"
-q "value[-1]"
# Pipe operations
-q "definition.parts[?path=='model.tmdl'] | [0]"
-q "definition.parts[?path=='definition/tables/Sales.tmdl'].payload | [0]"
# Projections (select specific fields)
-q "value[].{name: displayName, id: id, type: type}"
# Length/count
-q "value | length"
# Multi-select list
-q "value[].[displayName, id, type]"
# Flatten
-q "value[].items[]"
# Sort
-q "sort_by(value, &displayName)"
# Boolean logic
-q "value[?type=='Lakehouse' && contains(displayName, 'prod')]"
-q "value[?type=='Lakehouse' || type=='Warehouse']"
# Contains
-q "contains(value[].type, 'Lakehouse')"Common Error Scenarios
Authentication Issues
# 403 Forbidden - Check authentication
fab auth login
# 401 Unauthorized - Token expired, re-authenticate
fab auth login
# Use service principal for automation
fab auth login -u <client-id> -p <client-secret> --tenant <tenant-id>Resource Not Found
# 404 Not Found - Check resource exists
fab exists "Production.Workspace/Sales.SemanticModel"
# List available resources
fab ls "Production.Workspace"
# Get resource ID for API calls
fab get "Production.Workspace/Sales.SemanticModel" -q "id"Job Failures
# Check job status
fab job run-status "Production.Workspace/ETL.Notebook" --id <job-id>
# View job history for patterns
fab job run-list "Production.Workspace/ETL.Notebook"
# Run with timeout to prevent hanging
fab job run "Production.Workspace/ETL.Notebook" --timeout 300API Errors
# 400 Bad Request - Check JSON payload
fab api -X post "workspaces/<ws-id>/items" -i /tmp/payload.json --show_headers
# Debug with headers
fab api workspaces --show_headers
# Save response to inspect
fab api workspaces -o /tmp/debug.jsonPerformance Tips
1. Use `ls` instead of `get` for checking existence - 10-20x faster 2. Use `exists` before `get` operations - Avoids expensive failed gets 3. Filter with JMESPath `-q` - Reduce response size 4. Use GUIDs in automation - More stable than display names 5. Batch exports - Export workspace with -a instead of individual items 6. Parallel job execution - Use job start + polling for multiple jobs 7. Cache workspace/item IDs - Avoid repeated get calls for IDs 8. Use appropriate API audience - Power BI API is faster for dataset queries
Security Best Practices
1. Use service principals for automation - Don't use interactive auth in scripts 2. Store credentials securely - Use environment variables or key vaults 3. Use least-privilege access - Grant minimal required permissions 4. Audit API calls - Log all API operations in production 5. Validate inputs - Sanitize user inputs before passing to API 6. Use force flag carefully - -f skips confirmations, easy to delete wrong resources
Report Operations
Get Report Info
# Check exists
fab exists "ws.Workspace/Report.Report"
# Get properties
fab get "ws.Workspace/Report.Report"
# Get ID
fab get "ws.Workspace/Report.Report" -q "id"Get Report Definition
# Full definition
fab get "ws.Workspace/Report.Report" -q "definition"
# Save to file
fab get "ws.Workspace/Report.Report" -q "definition" -o /tmp/report-def.json
# Specific parts
fab get "ws.Workspace/Report.Report" -q "definition.parts[?path=='definition/report.json'].payload | [0]"Get Connected Model
# Get model reference from definition.pbir
fab get "ws.Workspace/Report.Report" -q "definition.parts[?contains(path, 'definition.pbir')].payload | [0]"Output shows byConnection.connectionString with semanticmodelid.
Export Report
1. Export to local directory:
fab export "ws.Workspace/Report.Report" -o /tmp/exports -f2. Creates structure:
Report.Report/
├── .platform
├── definition.pbir
└── definition/
├── report.json
├── version.json
└── pages/
└── {page-id}/
├── page.json
└── visuals/{visual-id}/visual.jsonImport Report
1. Import from local PBIP:
fab import "ws.Workspace/Report.Report" -i /tmp/exports/Report.Report -f2. Import with new name:
fab import "ws.Workspace/NewName.Report" -i /tmp/exports/Report.Report -fCopy Report Between Workspaces
fab cp "dev.Workspace/Report.Report" "prod.Workspace" -fCreate Blank Report
1. Get model ID:
fab get "ws.Workspace/Model.SemanticModel" -q "id"2. Create report via API:
WS_ID=$(fab get "ws.Workspace" -q "id" | tr -d '"')
fab api -X post "workspaces/$WS_ID/reports" -i '{
"displayName": "New Report",
"datasetId": "<model-id>"
}'Update Report Properties
# Rename
fab set "ws.Workspace/Report.Report" -q displayName -i "New Name"
# Update description
fab set "ws.Workspace/Report.Report" -q description -i "Description text"Rebind to Different Model
1. Get new model ID:
fab get "ws.Workspace/NewModel.SemanticModel" -q "id"2. Rebind:
fab set "ws.Workspace/Report.Report" -q semanticModelId -i "<new-model-id>"Delete Report
fab rm "ws.Workspace/Report.Report" -fList Pages
fab get "ws.Workspace/Report.Report" -q "definition.parts[?contains(path, 'page.json')].path"List Visuals
fab get "ws.Workspace/Report.Report" -q "definition.parts[?contains(path, '/visuals/')].path"Count Visuals by Type
1. Export visuals:
fab get "ws.Workspace/Report.Report" -q "definition.parts[?contains(path,'/visuals/')]" > /tmp/visuals.json2. Count by type:
jq -r '.[] | .payload.visual.visualType' < /tmp/visuals.json | sort | uniq -c | sort -rnExtract Fields Used in Report
1. Export visuals (if not done):
fab get "ws.Workspace/Report.Report" -q "definition.parts[?contains(path,'/visuals/')]" > /tmp/visuals.json2. List unique fields:
jq -r '[.[] | (.payload.visual.query.queryState // {} | to_entries[] | .value.projections[]? | if .field.Column then "\(.field.Column.Expression.SourceRef.Entity).\(.field.Column.Property)" elif .field.Measure then "\(.field.Measure.Expression.SourceRef.Entity).\(.field.Measure.Property)" else empty end)] | unique | sort | .[]' < /tmp/visuals.jsonValidate Fields Against Model
1. Export report:
fab export "ws.Workspace/Report.Report" -o /tmp/report -f2. Extract field references:
find /tmp/report -name "visual.json" -exec grep -B2 '"Property":' {} \; | \
grep -E '"Entity":|"Property":' | paste -d' ' - - | \
sed 's/.*"Entity": "\([^"]*\)".*"Property": "\([^"]*\)".*/\1.\2/' | sort -u3. Compare against model definition to find missing fields.
Report Permissions
1. Get IDs:
WS_ID=$(fab get "ws.Workspace" -q "id" | tr -d '"')
REPORT_ID=$(fab get "ws.Workspace/Report.Report" -q "id" | tr -d '"')2. List users:
fab api -A powerbi "groups/$WS_ID/reports/$REPORT_ID/users"3. Add user:
fab api -A powerbi "groups/$WS_ID/reports/$REPORT_ID/users" -X post -i '{
"emailAddress": "user@domain.com",
"reportUserAccessRight": "View"
}'Deploy Report (Dev to Prod)
1. Export from dev:
fab export "dev.Workspace/Report.Report" -o /tmp/deploy -f2. Import to prod:
fab import "prod.Workspace/Report.Report" -i /tmp/deploy/Report.Report -f3. Verify:
fab exists "prod.Workspace/Report.Report"Clone Report with Different Model
1. Export source:
fab export "ws.Workspace/Template.Report" -o /tmp/clone -f2. Edit /tmp/clone/Template.Report/definition.pbir to update semanticmodelid
3. Import as new report:
fab import "ws.Workspace/NewReport.Report" -i /tmp/clone/Template.Report -fTroubleshooting
Report Not Found
fab exists "ws.Workspace"
fab ls "ws.Workspace" | grep -i reportModel Binding Issues
# Check current binding
fab get "ws.Workspace/Report.Report" -q "definition.parts[?contains(path, 'definition.pbir')].payload | [0]"
# Rebind
fab set "ws.Workspace/Report.Report" -q semanticModelId -i "<model-id>"Import Fails
# Verify structure
ls -R /tmp/exports/Report.Report/
# Check definition is valid JSON
fab get "ws.Workspace/Report.Report" -q "definition" | jq . > /dev/null && echo "Valid"Semantic Model Operations
Comprehensive guide for working with semantic models (Power BI datasets) using the Fabric CLI.
Overview
Semantic models in Fabric use TMDL (Tabular Model Definition Language) format for their definitions. This guide covers getting, updating, exporting, and managing semantic models.
Getting Model Information
Basic Model Info
# Check if model exists
fab exists "Production.Workspace/Sales.SemanticModel"
# Get model properties
fab get "Production.Workspace/Sales.SemanticModel"
# Get model with all details (verbose)
fab get "Production.Workspace/Sales.SemanticModel" -v
# Get only model ID
fab get "Production.Workspace/Sales.SemanticModel" -q "id"Get Model Definition
The model definition contains all TMDL parts (tables, measures, relationships, etc.):
# Get full definition (all TMDL parts)
fab get "Production.Workspace/Sales.SemanticModel" -q "definition"
# Save definition to file
fab get "Production.Workspace/Sales.SemanticModel" -q "definition" -o /tmp/model-def.jsonGet Specific TMDL Parts
# Get model.tmdl (main model properties)
fab get "Production.Workspace/Sales.SemanticModel" -q "definition.parts[?path=='model.tmdl'].payload | [0]"
# Get specific table definition
fab get "Production.Workspace/Sales.SemanticModel" -q "definition.parts[?path=='definition/tables/Customers.tmdl'].payload | [0]"
# Get all table definitions
fab get "Production.Workspace/Sales.SemanticModel" -q "definition.parts[?starts_with(path, 'definition/tables/')]"
# Get relationships.tmdl
fab get "Production.Workspace/Sales.SemanticModel" -q "definition.parts[?path=='definition/relationships.tmdl'].payload | [0]"
# Get functions.tmdl (DAX functions)
fab get "Production.Workspace/Sales.SemanticModel" -q "definition.parts[?path=='definition/functions.tmdl'].payload | [0]"
# Get all definition part paths (for reference)
fab get "Production.Workspace/Sales.SemanticModel" -q "definition.parts[].path"Exporting Models
Export as PBIP (Power BI Project)
PBIP format is best for local development in Power BI Desktop or Tabular Editor:
# Export using the export script
python3 scripts/export_semantic_model_as_pbip.py \
"Production.Workspace/Sales.SemanticModel" -o /tmp/exportsExport as TMDL
The export script creates PBIP format which includes TMDL in the definition folder:
python3 scripts/export_semantic_model_as_pbip.py \
"Production.Workspace/Sales.SemanticModel" -o /tmp/exports
# TMDL files will be in: /tmp/exports/Sales.SemanticModel/definition/Export Specific Parts Only
# Export just tables
fab get "Production.Workspace/Sales.SemanticModel" -q "definition.parts[?starts_with(path, 'definition/tables/')]" -o /tmp/tables.json
# Export just measures (within tables)
fab get "Production.Workspace/Sales.SemanticModel" -q "definition.parts[?contains(path, '/tables/')]" | grep -A 20 "measure"Listing Model Contents
# List all items in model (if OneLake enabled)
fab ls "Production.Workspace/Sales.SemanticModel"
# Query model structure via API
fab api workspaces -q "value[?displayName=='Production'].id | [0]" | xargs -I {} \
fab api "workspaces/{}/items" -q "value[?type=='SemanticModel']"Updating Model Definitions
CRITICAL: When updating semantic models, you must: 1. Get the full definition 2. Modify the specific parts you want to change 3. Include ALL parts in the update request (modified + unmodified) 4. Never include .platform file 5. Test immediately
Update Workflow
# 1. Get workspace and model IDs
WS_ID=$(fab get "Production.Workspace" -q "id")
MODEL_ID=$(fab get "Production.Workspace/Sales.SemanticModel" -q "id")
# 2. Get current definition
fab get "Production.Workspace/Sales.SemanticModel" -q "definition" -o /tmp/current-def.json
# 3. Modify definition (edit JSON file or use script)
# ... modify /tmp/current-def.json ...
# 4. Wrap definition in update request
cat > /tmp/update-request.json <<EOF
{
"definition": $(cat /tmp/current-def.json)
}
EOF
# 5. Update via API
fab api -X post "workspaces/$WS_ID/semanticModels/$MODEL_ID/updateDefinition" \
-i /tmp/update-request.json \
--show_headers
# 6. Extract operation ID from Location header and poll status
OPERATION_ID="<extracted-from-Location-header>"
fab api "operations/$OPERATION_ID"Example: Add a Measure
# Python script to add measure to definition
import json
with open('/tmp/current-def.json', 'r') as f:
definition = json.load(f)
# Find the table's TMDL part
for part in definition['parts']:
if part['path'] == 'definition/tables/Sales.tmdl':
# Decode base64 content
import base64
tmdl_content = base64.b64decode(part['payload']).decode('utf-8')
# Add measure (simplified - real implementation needs proper TMDL syntax)
measure_tmdl = """
measure 'Total Revenue' = SUM(Sales[Amount])
formatString: #,0.00
displayFolder: "KPIs"
"""
tmdl_content += measure_tmdl
# Re-encode
part['payload'] = base64.b64encode(tmdl_content.encode('utf-8')).decode('utf-8')
# Save modified definition
with open('/tmp/modified-def.json', 'w') as f:
json.dump(definition, f)Executing DAX Queries
Use Power BI API to execute DAX queries against semantic models:
# Get model ID
MODEL_ID=$(fab get "Production.Workspace/Sales.SemanticModel" -q "id")
# Execute simple DAX query
fab api -A powerbi "datasets/$MODEL_ID/executeQueries" -X post -i '{
"queries": [{
"query": "EVALUATE VALUES(Date[Year])"
}]
}'
# Execute TOPN query
fab api -A powerbi "datasets/$MODEL_ID/executeQueries" -X post -i '{
"queries": [{
"query": "EVALUATE TOPN(10, Sales, Sales[Amount], DESC)"
}]
}'
# Execute multiple queries
fab api -A powerbi "datasets/$MODEL_ID/executeQueries" -X post -i '{
"queries": [
{"query": "EVALUATE VALUES(Date[Year])"},
{"query": "EVALUATE SUMMARIZE(Sales, Date[Year], \"Total\", SUM(Sales[Amount]))"}
],
"serializerSettings": {
"includeNulls": false
}
}'
# Execute query with parameters
fab api -A powerbi "datasets/$MODEL_ID/executeQueries" -X post -i '{
"queries": [{
"query": "EVALUATE FILTER(Sales, Sales[Year] = @Year)",
"parameters": [
{"name": "@Year", "value": "2024"}
]
}]
}'Using the DAX query script
python3 scripts/execute_dax.py \
--workspace "Production.Workspace" \
--model "Sales.SemanticModel" \
--query "EVALUATE TOPN(10, Sales)" \
--output /tmp/results.jsonRefreshing Models
# Get workspace and model IDs
WS_ID=$(fab get "Production.Workspace" -q "id")
MODEL_ID=$(fab get "Production.Workspace/Sales.SemanticModel" -q "id")
# Trigger full refresh
fab api -A powerbi "groups/$WS_ID/datasets/$MODEL_ID/refreshes" -X post -i '{"type":"Full"}'
# Check latest refresh status
fab api -A powerbi "groups/$WS_ID/datasets/$MODEL_ID/refreshes?\$top=1"
# Get refresh history
fab api -A powerbi "groups/$WS_ID/datasets/$MODEL_ID/refreshes"
# Cancel refresh
REFRESH_ID="<refresh-request-id>"
fab api -A powerbi "groups/$WS_ID/datasets/$MODEL_ID/refreshes/$REFRESH_ID" -X deleteModel Refresh Schedule
MODEL_ID=$(fab get "Production.Workspace/Sales.SemanticModel" -q "id")
# Get current schedule
fab api -A powerbi "datasets/$MODEL_ID/refreshSchedule"
# Update schedule (daily at 2 AM)
fab api -A powerbi "datasets/$MODEL_ID/refreshSchedule" -X patch -i '{
"enabled": true,
"days": ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
"times": ["02:00"],
"localTimeZoneId": "UTC"
}'
# Disable schedule
fab api -A powerbi "datasets/$MODEL_ID/refreshSchedule" -X patch -i '{
"enabled": false
}'Copying Models
# Copy semantic model between workspaces (full paths required)
fab cp "Dev.Workspace/Sales.SemanticModel" "Production.Workspace/Sales.SemanticModel" -f
# Copy with new name
fab cp "Dev.Workspace/Sales.SemanticModel" "Production.Workspace/SalesProduction.SemanticModel" -f
# Note: Both source and destination must include workspace.Workspace/model.SemanticModel
# This copies the definition, not data or refreshesModel Deployment Workflow
Dev to Production
#!/bin/bash
DEV_WS="Development.Workspace"
PROD_WS="Production.Workspace"
MODEL_NAME="Sales.SemanticModel"
# 1. Export from dev
fab export "$DEV_WS/$MODEL_NAME" -o /tmp/deployment
# 2. Test locally (optional - requires Power BI Desktop)
# Open /tmp/deployment/Sales/*.pbip in Power BI Desktop
# 3. Import to production
fab import "$PROD_WS/$MODEL_NAME" -i /tmp/deployment/$MODEL_NAME
# 4. Trigger refresh in production
PROD_MODEL_ID=$(fab get "$PROD_WS/$MODEL_NAME" -q "id")
fab api -A powerbi "datasets/$PROD_MODEL_ID/refreshes" -X post -i '{"type": "Full"}'
# 5. Monitor refresh
sleep 10
fab api -A powerbi "datasets/$PROD_MODEL_ID/refreshes" -q "value[0]"Working with Model Metadata
Update Display Name
fab set "Production.Workspace/Sales.SemanticModel" -q displayName -i "Sales Analytics Model"Update Description
fab set "Production.Workspace/Sales.SemanticModel" -q description -i "Primary sales analytics semantic model for production reporting"Advanced Patterns
Extract All Measures
# Get all table definitions containing measures
fab get "Production.Workspace/Sales.SemanticModel" -q "definition.parts[?contains(path, '/tables/')]" -o /tmp/tables.json
# Process with script to extract measures
python3 << 'EOF'
import json
import base64
with open('/tmp/tables.json', 'r') as f:
parts = json.load(f)
measures = []
for part in parts:
if 'tables' in part['path']:
content = base64.b64decode(part['payload']).decode('utf-8')
# Extract measure definitions (simple regex - real parser needed for production)
import re
measure_blocks = re.findall(r'measure\s+[^\n]+\s*=.*?(?=\n\s*(?:measure|column|$))', content, re.DOTALL)
measures.extend(measure_blocks)
for i, measure in enumerate(measures, 1):
print(f"\n--- Measure {i} ---")
print(measure)
EOFCompare Models (Diff)
# Export both models
fab get "Production.Workspace/Sales.SemanticModel" -q "definition" -o /tmp/model1-def.json
fab get "Dev.Workspace/Sales.SemanticModel" -q "definition" -o /tmp/model2-def.json
# Use diff tool
diff <(jq -S . /tmp/model1-def.json) <(jq -S . /tmp/model2-def.json)
# jq -S sorts keys for consistent comparisonBackup Model Definition
#!/bin/bash
WORKSPACE="Production.Workspace"
MODEL="Sales.SemanticModel"
BACKUP_DIR="/backups/$(date +%Y%m%d)"
mkdir -p "$BACKUP_DIR"
# Export as multiple formats for redundancy
fab get "$WORKSPACE/$MODEL" -q "definition" -o "$BACKUP_DIR/definition.json"
# Export as PBIP
python3 scripts/export_semantic_model_as_pbip.py \
"$WORKSPACE/$MODEL" -o "$BACKUP_DIR/pbip"
# Save metadata
fab get "$WORKSPACE/$MODEL" -o "$BACKUP_DIR/metadata.json"
echo "Backup completed: $BACKUP_DIR"TMDL Structure Reference
A semantic model's TMDL definition consists of these parts:
model.tmdl # Model properties, culture, compatibility
.platform # Git integration metadata (exclude from updates)
definition/
├── model.tmdl # Alternative location for model properties
├── database.tmdl # Database properties
├── roles.tmdl # Row-level security roles
├── relationships.tmdl # Relationships between tables
├── functions.tmdl # DAX user-defined functions
├── expressions/ # M queries for data sources
│ ├── Source1.tmdl
│ └── Source2.tmdl
└── tables/ # Table definitions
├── Customers.tmdl # Columns, measures, hierarchies
├── Sales.tmdl
├── Products.tmdl
└── Date.tmdlCommon TMDL Parts to Query
MODEL="Production.Workspace/Sales.SemanticModel"
# Model properties
fab get "$MODEL" -q "definition.parts[?path=='model.tmdl'].payload | [0]"
# Roles and RLS
fab get "$MODEL" -q "definition.parts[?path=='definition/roles.tmdl'].payload | [0]"
# Relationships
fab get "$MODEL" -q "definition.parts[?path=='definition/relationships.tmdl'].payload | [0]"
# Data source expressions
fab get "$MODEL" -q "definition.parts[?starts_with(path, 'definition/expressions/')]"
# All tables
fab get "$MODEL" -q "definition.parts[?starts_with(path, 'definition/tables/')].path"Troubleshooting
Model Not Found
# Verify workspace exists
fab exists "Production.Workspace"
# List semantic models in workspace
WS_ID=$(fab get "Production.Workspace" -q "id")
fab api "workspaces/$WS_ID/items" -q "value[?type=='SemanticModel']"Update Definition Fails
Common issues: 1. Included `.platform` file: Never include this in updates 2. Missing parts: Must include ALL parts, not just modified ones 3. Invalid TMDL syntax: Validate TMDL before updating 4. Encoding issues: Ensure base64 encoding is correct
# Debug update operation
fab api "operations/$OPERATION_ID" -q "error"DAX Query Errors
# Check model is online
fab get "Production.Workspace/Sales.SemanticModel" -q "properties"
# Try simple query first
MODEL_ID=$(fab get "Production.Workspace/Sales.SemanticModel" -q "id")
fab api -A powerbi "datasets/$MODEL_ID/executeQueries" -X post -i '{
"queries": [{"query": "EVALUATE {1}"}]
}'Storage Mode
Check table partition mode to determine if model is Direct Lake, Import, or DirectQuery.
# Get table definition and check partition mode
fab get "ws.Workspace/Model.SemanticModel" -q "definition.parts[?contains(path, 'tables/TableName')].payload | [0]"Output shows partition type:
# Direct Lake
partition TableName = entity
mode: directLake
source
entityName: table_name
schemaName: schema
expressionSource: DatabaseQuery
# Import
partition TableName = m
mode: import
source =
let
Source = Sql.Database("connection", "database"),
Data = Source{[Schema="schema",Item="table"]}[Data]
in
DataWorkspace Access
# Get workspace ID
fab get "ws.Workspace" -q "id"
# List users with access
fab api -A powerbi "groups/<workspace-id>/users"Output:
{
"value": [
{
"emailAddress": "user@domain.com",
"groupUserAccessRight": "Admin",
"displayName": "User Name",
"principalType": "User"
}
]
}Access rights: Admin, Member, Contributor, Viewer
Find Reports Using a Model
Check report's definition.pbir for byConnection.semanticmodelid:
# Get model ID
fab get "ws.Workspace/Model.SemanticModel" -q "id"
# Check a report's connection
fab get "ws.Workspace/Report.Report" -q "definition.parts[?contains(path, 'definition.pbir')].payload | [0]"Output:
{
"datasetReference": {
"byConnection": {
"connectionString": "...semanticmodelid=bee906a0-255e-..."
}
}
}To find all reports using a model, check each report's definition.pbir for matching semanticmodelid.
Performance Tips
1. Cache model IDs: Don't repeatedly query for the same ID 2. Use JMESPath filtering: Get only what you need 3. Batch DAX queries: Combine multiple queries in one request 4. Export during off-hours: Large model exports can be slow 5. Use Power BI API for queries: It's optimized for DAX execution
Security Considerations
1. Row-Level Security: Check roles before exposing data 2. Credentials in data sources: Don't commit data source credentials 3. Sensitive measures: Review calculated columns/measures for sensitive logic 4. Export restrictions: Ensure exported models don't contain sensitive data
Related Scripts
scripts/create_direct_lake_model.py- Create Direct Lake model from lakehouse tablescripts/export_semantic_model_as_pbip.py- Export model as PBIPscripts/execute_dax.py- Execute DAX queries
Workspace Operations
Comprehensive guide for managing Fabric workspaces using the Fabric CLI.
Overview
Workspaces are containers for Fabric items and provide collaboration and security boundaries. This guide covers workspace management, configuration, and operations.
Listing Workspaces
List All Workspaces
# Simple list
fab ls
# Detailed list with metadata
fab ls -l
# List with hidden tenant-level items
fab ls -la
# Hidden items include: capacities, connections, domains, gatewaysFilter Workspaces
# Using API with JMESPath query
fab api workspaces -q "value[].{name: displayName, id: id, type: type}"
# Filter by name pattern
fab api workspaces -q "value[?contains(displayName, 'Production')]"
# Filter by capacity
fab api workspaces -q "value[?capacityId=='<capacity-id>']"
# Get workspace count
fab api workspaces -q "value | length"Getting Workspace Information
Basic Workspace Info
# Check if workspace exists
fab exists "Production.Workspace"
# Get workspace details
fab get "Production.Workspace"
# Get specific property
fab get "Production.Workspace" -q "id"
fab get "Production.Workspace" -q "capacityId"
fab get "Production.Workspace" -q "description"
# Get all properties (verbose)
fab get "Production.Workspace" -v
# Save to file
fab get "Production.Workspace" -o /tmp/workspace-info.jsonGet Workspace Configuration
# Get Spark settings
fab get "Production.Workspace" -q "sparkSettings"
# Get Spark runtime version
fab get "Production.Workspace" -q "sparkSettings.environment.runtimeVersion"
# Get default Spark pool
fab get "Production.Workspace" -q "sparkSettings.pool.defaultPool"Creating Workspaces
Create with Default Capacity
# Use CLI-configured default capacity
fab mkdir "NewWorkspace.Workspace"
# Verify capacity configuration first
fab api workspaces -q "value[0].capacityId"Create with Specific Capacity
# Assign to specific capacity
fab mkdir "Production Workspace.Workspace" -P capacityname=ProductionCapacity
# Get capacity name from capacity list
fab ls -la | grep CapacityCreate without Capacity
# Create in shared capacity (not recommended for production)
fab mkdir "Dev Workspace.Workspace" -P capacityname=noneListing Workspace Contents
List Items in Workspace
# Simple list
fab ls "Production.Workspace"
# Detailed list with metadata
fab ls "Production.Workspace" -l
# Include hidden items (Spark pools, managed identities, etc.)
fab ls "Production.Workspace" -la
# Hidden workspace items include:
# - External Data Shares
# - Managed Identities
# - Managed Private Endpoints
# - Spark PoolsFilter Items by Type
WS_ID=$(fab get "Production.Workspace" -q "id")
# List semantic models only
fab api "workspaces/$WS_ID/items" -q "value[?type=='SemanticModel']"
# List reports only
fab api "workspaces/$WS_ID/items" -q "value[?type=='Report']"
# List notebooks
fab api "workspaces/$WS_ID/items" -q "value[?type=='Notebook']"
# List lakehouses
fab api "workspaces/$WS_ID/items" -q "value[?type=='Lakehouse']"
# Count items by type
fab api "workspaces/$WS_ID/items" -q "value | group_by(@, &type)"Updating Workspaces
Update Display Name
fab set "OldName.Workspace" -q displayName -i "NewName"
# Note: This changes the display name, not the workspace IDUpdate Description
fab set "Production.Workspace" -q description -i "Production environment for enterprise analytics"Configure Spark Settings
# Set Spark runtime version
fab set "Production.Workspace" -q sparkSettings.environment.runtimeVersion -i 1.2
# Set starter pool as default
fab set "Production.Workspace" -q sparkSettings.pool.defaultPool -i '{
"name": "Starter Pool",
"type": "Workspace"
}'
# Set custom workspace pool
fab set "Production.Workspace" -q sparkSettings.pool.defaultPool -i '{
"name": "HighMemoryPool",
"type": "Workspace",
"id": "<pool-id>"
}'Capacity Management
Assign Workspace to Capacity
# Get capacity ID
CAPACITY_ID=$(fab api -A azure "subscriptions/<subscription-id>/providers/Microsoft.Fabric/capacities?api-version=2023-11-01" -q "value[?name=='MyCapacity'].id | [0]")
# Assign workspace
fab assign "Production.Workspace" -P capacityId=$CAPACITY_IDUnassign from Capacity
# Move to shared capacity
fab unassign "Dev.Workspace"List Workspaces by Capacity
# Get all workspaces
fab api workspaces -q "value[] | group_by(@, &capacityId)"
# List workspaces on specific capacity
fab api workspaces -q "value[?capacityId=='<capacity-id>'].displayName"Workspace Migration
Export Entire Workspace
# Export all items
fab export "Production.Workspace" -o /tmp/workspace-backup -a
# This exports all supported item types:
# - Notebooks
# - Data Pipelines
# - Reports
# - Semantic Models
# - etc.Selective Export
#!/bin/bash
WORKSPACE="Production.Workspace"
OUTPUT_DIR="/tmp/migration"
# Export only semantic models
WS_ID=$(fab get "$WORKSPACE" -q "id")
MODELS=$(fab api "workspaces/$WS_ID/items" -q "value[?type=='SemanticModel'].displayName")
for MODEL in $MODELS; do
fab export "$WORKSPACE/$MODEL.SemanticModel" -o "$OUTPUT_DIR/models"
done
# Export only reports
REPORTS=$(fab api "workspaces/$WS_ID/items" -q "value[?type=='Report'].displayName")
for REPORT in $REPORTS; do
fab export "$WORKSPACE/$REPORT.Report" -o "$OUTPUT_DIR/reports"
doneCopy Workspace Contents
# Copy all items to another workspace (interactive selection)
fab cp "Source.Workspace" "Target.Workspace"
# Copy specific items
fab cp "Source.Workspace/Model.SemanticModel" "Target.Workspace"
fab cp "Source.Workspace/Report.Report" "Target.Workspace"
fab cp "Source.Workspace/Notebook.Notebook" "Target.Workspace"Deleting Workspaces
Delete with Confirmation
# Interactive confirmation (lists items first)
fab rm "OldWorkspace.Workspace"Force Delete
# Delete workspace and all contents without confirmation
# ⚠️ DANGEROUS - Cannot be undone
fab rm "TestWorkspace.Workspace" -fNavigation
Change to Workspace
# Navigate to workspace
fab cd "Production.Workspace"
# Verify current location
fab pwd
# Navigate to personal workspace
fab cd ~Relative Navigation
# From workspace to another
fab cd "../Dev.Workspace"
# To parent (tenant level)
fab cd ..Workspace Inventory
Get Complete Inventory
#!/bin/bash
WORKSPACE="Production.Workspace"
WS_ID=$(fab get "$WORKSPACE" -q "id")
echo "=== Workspace: $WORKSPACE ==="
echo
# Get all items
ITEMS=$(fab api "workspaces/$WS_ID/items")
# Count by type
echo "Item Counts:"
echo "$ITEMS" | jq -r '.value | group_by(.type) | map({type: .[0].type, count: length}) | .[] | "\(.type): \(.count)"'
echo
echo "Total Items: $(echo "$ITEMS" | jq '.value | length')"
# List items
echo
echo "=== Items ==="
echo "$ITEMS" | jq -r '.value[] | "\(.type): \(.displayName)"' | sortGenerate Inventory Report
#!/bin/bash
OUTPUT_FILE="/tmp/workspace-inventory.csv"
echo "Workspace,Item Type,Item Name,Created Date,Modified Date" > "$OUTPUT_FILE"
# Get all workspaces
WORKSPACES=$(fab api workspaces -q "value[].{name: displayName, id: id}")
echo "$WORKSPACES" | jq -r '.[] | [.name, .id] | @tsv' | while IFS=$'\t' read -r WS_NAME WS_ID; do
# Get items in workspace
ITEMS=$(fab api "workspaces/$WS_ID/items")
echo "$ITEMS" | jq -r --arg ws "$WS_NAME" '.value[] | [$ws, .type, .displayName, .createdDate, .lastModifiedDate] | @csv' >> "$OUTPUT_FILE"
done
echo "Inventory saved to $OUTPUT_FILE"Workspace Permissions
List Workspace Users
WS_ID=$(fab get "Production.Workspace" -q "id")
# List users with access
fab api -A powerbi "groups/$WS_ID/users"Add User to Workspace
WS_ID=$(fab get "Production.Workspace" -q "id")
# Add user as member
fab api -A powerbi "groups/$WS_ID/users" -X post -i '{
"emailAddress": "user@company.com",
"groupUserAccessRight": "Member"
}'
# Access levels: Admin, Member, Contributor, ViewerRemove User from Workspace
WS_ID=$(fab get "Production.Workspace" -q "id")
# Remove user
fab api -A powerbi "groups/$WS_ID/users/user@company.com" -X deleteWorkspace Settings
Git Integration
WS_ID=$(fab get "Production.Workspace" -q "id")
# Get Git connection status
fab api "workspaces/$WS_ID/git/connection"
# Connect to Git (requires Git integration setup)
fab api -X post "workspaces/$WS_ID/git/initializeConnection" -i '{
"gitProviderDetails": {
"organizationName": "myorg",
"projectName": "fabric-project",
"repositoryName": "production",
"branchName": "main",
"directoryName": "/workspace-content"
}
}'Advanced Workflows
Clone Workspace
#!/bin/bash
SOURCE_WS="Template.Workspace"
TARGET_WS="New Project.Workspace"
CAPACITY="MyCapacity"
# 1. Create target workspace
fab mkdir "$TARGET_WS" -P capacityname=$CAPACITY
# 2. Export all items from source
fab export "$SOURCE_WS" -o /tmp/clone -a
# 3. Import items to target
for ITEM in /tmp/clone/*; do
ITEM_NAME=$(basename "$ITEM")
fab import "$TARGET_WS/$ITEM_NAME" -i "$ITEM"
done
echo "Workspace cloned successfully"Workspace Comparison
#!/bin/bash
WS1="Production.Workspace"
WS2="Development.Workspace"
WS1_ID=$(fab get "$WS1" -q "id")
WS2_ID=$(fab get "$WS2" -q "id")
echo "=== Comparing Workspaces ==="
echo
echo "--- $WS1 ---"
fab api "workspaces/$WS1_ID/items" -q "value[].{type: type, name: displayName}" | jq -r '.[] | "\(.type): \(.name)"' | sort > /tmp/ws1.txt
echo "--- $WS2 ---"
fab api "workspaces/$WS2_ID/items" -q "value[].{type: type, name: displayName}" | jq -r '.[] | "\(.type): \(.name)"' | sort > /tmp/ws2.txt
echo
echo "=== Differences ==="
diff /tmp/ws1.txt /tmp/ws2.txt
rm /tmp/ws1.txt /tmp/ws2.txtBatch Workspace Operations
#!/bin/bash
# Update description for all production workspaces
PROD_WORKSPACES=$(fab api workspaces -q "value[?contains(displayName, 'Prod')].displayName")
for WS in $PROD_WORKSPACES; do
echo "Updating $WS..."
fab set "$WS.Workspace" -q description -i "Production environment - managed by Data Platform team"
doneWorkspace Monitoring
Monitor Workspace Activity
WS_ID=$(fab get "Production.Workspace" -q "id")
# Get activity events (requires admin access)
fab api -A powerbi "admin/activityevents?filter=Workspace%20eq%20'$WS_ID'"Track Workspace Size
#!/bin/bash
WORKSPACE="Production.Workspace"
WS_ID=$(fab get "$WORKSPACE" -q "id")
# Count items
ITEM_COUNT=$(fab api "workspaces/$WS_ID/items" -q "value | length")
# Count by type
echo "=== Workspace: $WORKSPACE ==="
echo "Total Items: $ITEM_COUNT"
echo
echo "Items by Type:"
fab api "workspaces/$WS_ID/items" -q "value | group_by(@, &type) | map({type: .[0].type, count: length}) | sort_by(.count) | reverse | .[]" | jq -r '"\(.type): \(.count)"'Troubleshooting
Workspace Not Found
# List all workspaces to verify name
fab ls | grep -i "production"
# Get by ID directly
fab api "workspaces/<workspace-id>"Capacity Issues
# Check workspace capacity assignment
fab get "Production.Workspace" -q "capacityId"
# List available capacities
fab ls -la | grep Capacity
# Verify capacity status (via Azure API)
fab api -A azure "subscriptions/<subscription-id>/providers/Microsoft.Fabric/capacities?api-version=2023-11-01" -q "value[].{name: name, state: properties.state, sku: sku.name}"Permission Errors
# Verify your access level
WS_ID=$(fab get "Production.Workspace" -q "id")
fab api -A powerbi "groups/$WS_ID/users" | grep "$(whoami)"
# Check if you're workspace admin
fab api -A powerbi "groups/$WS_ID/users" -q "value[?emailAddress=='your@email.com'].groupUserAccessRight"Best Practices
1. Naming conventions: Use consistent naming (e.g., "ProjectName - Environment") 2. Capacity planning: Assign workspaces to appropriate capacities 3. Access control: Use least-privilege principle for permissions 4. Git integration: Enable for production workspaces 5. Regular backups: Export critical workspaces periodically 6. Documentation: Maintain workspace descriptions 7. Monitoring: Track workspace activity and growth 8. Cleanup: Remove unused workspaces regularly
Performance Tips
1. Cache workspace IDs: Don't repeatedly query for same ID 2. Use JMESPath filters: Get only needed data 3. Parallel operations: Export multiple items concurrently 4. Batch updates: Group similar operations 5. Off-peak operations: Schedule large migrations during low usage
Security Considerations
1. Access reviews: Regularly audit workspace permissions 2. Sensitive data: Use appropriate security labels 3. Capacity isolation: Separate dev/test/prod workspaces 4. Git secrets: Don't commit credentials in Git-integrated workspaces 5. Audit logging: Enable and monitor activity logs
Related Scripts
scripts/download_workspace.py- Download complete workspace with all items and lakehouse files
Fabric CLI Utility Scripts
Python scripts extending fab CLI with common operations. All scripts use the same path syntax as fab commands.
Path Syntax
All scripts use Fabric path format: Workspace.Workspace/Item.ItemType
# Examples
"Sales.Workspace/Model.SemanticModel"
"Production.Workspace/LH.Lakehouse"
"Dev.Workspace/Report.Report"Scripts
create_direct_lake_model.py
Create a Direct Lake semantic model from lakehouse tables. This is the recommended approach for querying lakehouse data via DAX.
python3 create_direct_lake_model.py "src.Workspace/LH.Lakehouse" "dest.Workspace/Model.SemanticModel" -t schema.table
python3 create_direct_lake_model.py "Sales.Workspace/SalesLH.Lakehouse" "Sales.Workspace/Sales Model.SemanticModel" -t gold.ordersArguments:
source- Source lakehouse: Workspace.Workspace/Lakehouse.Lakehousedest- Destination model: Workspace.Workspace/Model.SemanticModel-t, --table- Table in schema.table format (required)
execute_dax.py
Execute DAX queries against semantic models.
python3 execute_dax.py "ws.Workspace/Model.SemanticModel" -q "EVALUATE VALUES('Date'[Year])"
python3 execute_dax.py "Sales.Workspace/Sales Model.SemanticModel" -q "EVALUATE TOPN(10, 'Orders')" --format csv
python3 execute_dax.py "ws.Workspace/Model.SemanticModel" -q "EVALUATE ROW(\"Total\", SUM('Sales'[Amount]))" -o results.jsonOptions:
-q, --query- DAX query (required)-o, --output- Output file--format- Output format: table (default), csv, json--include-nulls- Include null values
export_semantic_model_as_pbip.py
Export semantic model as PBIP (Power BI Project) format.
python3 export_semantic_model_as_pbip.py "ws.Workspace/Model.SemanticModel" -o ./output
python3 export_semantic_model_as_pbip.py "Sales.Workspace/Sales Model.SemanticModel" -o /tmp/exportsCreates complete PBIP structure with TMDL definition and blank report.
download_workspace.py
Download complete workspace with all items and lakehouse files.
python3 download_workspace.py "Sales.Workspace"
python3 download_workspace.py "Production.Workspace" ./backup
python3 download_workspace.py "Dev.Workspace" --no-lakehouse-filesOptions:
output_dir- Output directory (default: ./workspace_downloads/<name>)--no-lakehouse-files- Skip lakehouse file downloads
Requirements
- Python 3.10+
fabCLI installed and authenticated- For lakehouse file downloads:
azure-storage-file-datalake,azure-identity
# Mac version coming soon
{
"asConfiguration": {
"runtime": {
"isProcessWithUI": true
}
}
}MIT License
Copyright (c) Microsoft Corporation.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE
You are an expert in Power BI Project (PBIP) file structure.
If the powerbi-modeling-mcp MCP server is available, do not create or edit the TMDL files directly.
PBIP structure
root/
├── [Name].SemanticModel/
| ├── /definition # The semantic model definition using TMDL language
| ├── definition.pbism # The semantic model definition file
├── [Name].Report/
| ├── /definition # The report definition using PBIR format
| ├── definition.pbir # The report definition file with a byPath relative reference to the semantic model folder
└── [Name].pbip # A shortcut file to the report folderExample of a definition.pbism file
No modifications are needed—just create the file exactly as shown in the example.
{
"$schema": "https://developer.microsoft.com/json-schemas/fabric/item/semanticModel/definitionProperties/1.0.0/schema.json",
"version": "4.2",
"settings": {
"qnaEnabled": true
}
}Example of a definition.pbir file
The byPath property should reference the semantic model folder using a relative path like below.
{
"$schema": "https://developer.microsoft.com/json-schemas/fabric/item/report/definitionProperties/2.0.0/schema.json",
"version": "4.0",
"datasetReference": {
"byPath": {
"path": "../{Name of the Semantic Model}.SemanticModel"
}
}
}Example of a {Name of the Semantic Model}.pbip file
{
"$schema": "https://developer.microsoft.com/json-schemas/fabric/pbip/pbipProperties/1.0.0/schema.json",
"version": "1.0",
"artifacts": [
{
"report": {
"path": "{Name of the Semantic Model}.Report"
}
}
],
"settings": {
"enableAutoRecovery": true
}
}Open from PBIP
When asked to open/load the semantic model from a PBIP, you must only load the [Name].SemanticModel/definition folder. No other folder is suitable to load from semantic model developer tools.
Save to PBIP
When asked to save to a new PBIP folder make sure you create the folder and files from the structure above using the provided examples.
Creation of new semantic model
1. Create a PBIP folder for the semantic model following the structure above 2. Use the database_operations tool of the MCP server to Create a new database. 3. In the end of the modeling session, serialize as TMDL to the definition/ folder in the PBIP