Power BI is Microsoft's Business Intelligence solution - powerful, but often isolated from other systems. In this guide, we show you how to connect Power BI with automation using n8n and Make.com: automatically refresh data, distribute reports, and send alerts when KPIs change.

Before you read on
Does automation actually pay off for you? Take the 5-minute analysis — score, maturity level and an honest read on whether this path fits your situation. Free, report by email.
Start 5-min analysis →

Why Automate Power BI?

Typical Problems:

ProblemManual EffortAutomated Solution
Data RefreshDaily manualAutomatic on change
Report DistributionEmail exportAutomatic delivery
KPI MonitoringCheck dashboardProactive alerts
Data Source SyncMaintain ETL jobsEvent-based updates

Power BI REST API Basics

Setting Up API Access

  • Register Azure AD App:
  • - Azure Portal -> App registrations -> New registration

    - Name: "Power BI Automation"

    - Redirect URI: https://n8n.your-domain.com/oauth2/callback

  • Add Permissions:
  • - API permissions -> Add permission -> Power BI Service

    - Delegated: Dataset.ReadWrite.All, Report.Read.All

  • Create Client Secret:
  • - Certificates & secrets -> New client secret

    - Copy and store secret securely

    Authentication

    // Get OAuth2 token
    const tokenResponse = await fetch('https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token', {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: new URLSearchParams({
        client_id: 'YOUR_CLIENT_ID',
        client_secret: 'YOUR_CLIENT_SECRET',
        scope: 'https://analysis.windows.net/powerbi/api/.default',
        grant_type: 'client_credentials'
      })
    });
    
    const { access_token } = await tokenResponse.json();

    Workflow 1: Automatic Dataset Refresh

    The Goal

    Automatically refresh datasets when source data changes.

    Trigger Options

    Option A: Scheduled
    Schedule (daily 6:00 AM)
            |
        Power BI: Dataset Refresh
    
    Option B: Event-based
    Database (new data)
            |
        Power BI: Dataset Refresh
    
    Option C: Webhook
    External System (Webhook)
            |
        Power BI: Dataset Refresh

    n8n Implementation

    Node 1: Trigger (Schedule or Webhook)

    Node 2: Start Power BI Refresh

    // Node: HTTP Request
    {
      "method": "POST",
      "url": "https://api.powerbi.com/v1.0/myorg/groups/{{ $env.WORKSPACE_ID }}/datasets/{{ $env.DATASET_ID }}/refreshes",
      "headers": {
        "Authorization": "Bearer {{ $json.access_token }}",
        "Content-Type": "application/json"
      },
      "body": {
        "notifyOption": "MailOnFailure"
      }
    }

    Node 3: Check Refresh Status

    // Power BI Refresh is async - query status
    // Node: HTTP Request
    {
      "method": "GET",
      "url": "https://api.powerbi.com/v1.0/myorg/groups/{{ $env.WORKSPACE_ID }}/datasets/{{ $env.DATASET_ID }}/refreshes?$top=1",
      "headers": {
        "Authorization": "Bearer {{ $json.access_token }}"
      }
    }

    Node 4: Wait for Completion

    // Node: Wait + Loop
    const refreshStatus = $json.value[0].status;
    
    if (refreshStatus === 'Completed') {
      return { success: true };
    } else if (refreshStatus === 'Failed') {
      throw new Error('Refresh failed: ' + $json.value[0].serviceExceptionJson);
    } else {
      // Still in progress - check again
      await wait(30000); // 30 seconds
      // ... Loop
    }

    Build it or have it built?
    We implement this workflow for you — fully tested in 1-4 weeks. Fixed-price quote within 24h.
    Get a Quote →

    Workflow 2: Send Report via Email

    The Goal

    Automatically export reports as PDF and send via email.

    The Workflow

    Schedule (Monday 8:00 AM)
            |
        Power BI: Export report (PDF)
            |
        Wait for export
            |
        Download PDF
            |
        Send email with attachment

    n8n Implementation

    Step 1: Start Export

    // Node: HTTP Request
    {
      "method": "POST",
      "url": "https://api.powerbi.com/v1.0/myorg/groups/{{ $env.WORKSPACE_ID }}/reports/{{ $env.REPORT_ID }}/ExportTo",
      "headers": {
        "Authorization": "Bearer {{ $json.access_token }}",
        "Content-Type": "application/json"
      },
      "body": {
        "format": "PDF",
        "powerBIReportConfiguration": {
          "pages": [
            { "pageName": "ReportSection1" }
          ]
        }
      }
    }

    Step 2: Check Export Status

    // Node: HTTP Request (Loop until done)
    {
      "method": "GET",
      "url": "https://api.powerbi.com/v1.0/myorg/groups/{{ $env.WORKSPACE_ID }}/reports/{{ $env.REPORT_ID }}/exports/{{ $json.id }}",
      "headers": {
        "Authorization": "Bearer {{ $json.access_token }}"
      }
    }

    Step 3: Download PDF

    // Node: HTTP Request (Binary)
    {
      "method": "GET",
      "url": "https://api.powerbi.com/v1.0/myorg/groups/{{ $env.WORKSPACE_ID }}/reports/{{ $env.REPORT_ID }}/exports/{{ $json.id }}/file",
      "headers": {
        "Authorization": "Bearer {{ $json.access_token }}"
      },
      "responseFormat": "file"
    }

    Step 4: Send Email

    // Node: Send Email
    {
      "to": "management@company.com",
      "subject": "Weekly Sales Report - Week {{ $now.weekNumber }}",
      "body": "Please find the current sales report attached.",
      "attachments": [
        {
          "filename": "Sales-Report-Week{{ $now.weekNumber }}.pdf",
          "data": "{{ $binary.data }}"
        }
      ]
    }

    Workflow 3: KPI Alerts

    The Goal

    Get notified when KPIs exceed or fall below certain thresholds.

    The Workflow

    Schedule (hourly)
            |
        Power BI: Execute DAX query
            |
        Check KPI values
            |
        Threshold exceeded?
            |
        Yes: Send alert (Slack/Email)

    Execute DAX Query

    // Node: HTTP Request
    {
      "method": "POST",
      "url": "https://api.powerbi.com/v1.0/myorg/groups/{{ $env.WORKSPACE_ID }}/datasets/{{ $env.DATASET_ID }}/executeQueries",
      "headers": {
        "Authorization": "Bearer {{ $json.access_token }}",
        "Content-Type": "application/json"
      },
      "body": {
        "queries": [
          {
            "query": "EVALUATE SUMMARIZECOLUMNS('Date'[Month], 'Sales'[Total Revenue], 'Sales'[Order Count])"
          }
        ],
        "serializerSettings": {
          "includeNulls": true
        }
      }
    }

    Alert Logic

    // Node: Code
    const results = $json.results[0].tables[0].rows;
    const currentMonth = results[results.length - 1];
    
    const alerts = [];
    
    // Revenue Check
    if (currentMonth['Sales[Total Revenue]'] < 100000) {
      alerts.push({
        type: 'warning',
        kpi: 'Revenue',
        value: currentMonth['Sales[Total Revenue]'],
        threshold: 100000,
        message: 'Revenue below target!'
      });
    }
    
    // Order Count Check
    if (currentMonth['Sales[Order Count]'] < 500) {
      alerts.push({
        type: 'critical',
        kpi: 'Orders',
        value: currentMonth['Sales[Order Count]'],
        threshold: 500,
        message: 'Orders critically low!'
      });
    }
    
    return { alerts, hasAlerts: alerts.length > 0 };

    Slack Alert

    // Node: Slack (when hasAlerts = true)
    {
      "channel": "#kpi-alerts",
      "attachments": [
        {
          "color": "{{ $json.alerts[0].type === 'critical' ? 'danger' : 'warning' }}",
          "title": "KPI Alert",
          "fields": $json.alerts.map(a => ({
            "title": a.kpi,
            "value": `${a.value} (Target: ${a.threshold})`,
            "short": true
          }))
        }
      ]
    }

    Workflow 4: Push Data to Power BI

    Create Push Datasets

    Power BI supports push datasets for real-time data:

    // Create dataset
    {
      "method": "POST",
      "url": "https://api.powerbi.com/v1.0/myorg/groups/{{ $env.WORKSPACE_ID }}/datasets",
      "body": {
        "name": "Real-Time Sales",
        "defaultMode": "Push",
        "tables": [
          {
            "name": "Sales",
            "columns": [
              { "name": "Timestamp", "dataType": "DateTime" },
              { "name": "Product", "dataType": "String" },
              { "name": "Amount", "dataType": "Double" },
              { "name": "Quantity", "dataType": "Int64" }
            ]
          }
        ]
      }
    }

    Push Data

    // On new order: Send data to Power BI
    {
      "method": "POST",
      "url": "https://api.powerbi.com/v1.0/myorg/groups/{{ $env.WORKSPACE_ID }}/datasets/{{ $env.PUSH_DATASET_ID }}/tables/Sales/rows",
      "body": {
        "rows": [
          {
            "Timestamp": "{{ $now.toISO() }}",
            "Product": "{{ $json.product_name }}",
            "Amount": {{ $json.total }},
            "Quantity": {{ $json.quantity }}
          }
        ]
      }
    }

    Training or implementation?
    Whether you want to learn it yourself or have us build it — we offer both. Custom workshops from 2h or turnkey solutions.
    See Options →

    Make.com Scenario

    Modules for Power BI

    Make.com has native Power BI modules:

  • Power BI -> Refresh a Dataset
  • Power BI -> Export a Report
  • Power BI -> Execute a Query
  • Example Scenario

    Schedule (daily 6:00 AM)
            |
        Power BI: Refresh Dataset
            |
        Wait: 10 minutes
            |
        Power BI: Export Report to PDF
            |
        Wait: 5 minutes
            |
        Power BI: Get Export Status
            |
        Gmail: Send with Attachment

    Integration with Other Data Sources

    SQL Server -> Power BI

    SQL Server (new data)
            |
        Trigger: New rows
            |
        Power BI: Dataset Refresh

    Google Analytics -> Power BI

    Schedule (daily)
            |
        Google Analytics: Get report
            |
        Transform data
            |
        Power BI: Push Dataset

    Shopify -> Power BI (Real-time)

    This is a powerful addition to any e-commerce automation setup.

    Shopify Webhook (new order)
            |
        Format data
            |
        Power BI: Push to Real-Time Dataset

    Best Practices

    1. Mind the Refresh Limits

    Power BI PlanRefreshes/Day
    Pro8
    Premium48
    Premium per User48

    2. Error Handling

    // Catch refresh errors
    try {
      await refreshDataset();
    } catch (error) {
      if (error.status === 429) {
        // Rate limit - try again later
        await wait(3600000); // 1 hour
      } else if (error.status === 401) {
        // Token expired - re-authenticate
        await refreshToken();
      } else {
        await sendAlert(error);
      }
    }

    3. Use Incremental Refresh

    Instead of full refresh, only load new data:

    Power BI Desktop:
    - Enable Incremental Refresh
    - Define RangeStart/RangeEnd parameters
    - Only delta data is loaded

    4. Monitor Gateway Status

    // Check gateway status
    const gateways = await fetch(
      'https://api.powerbi.com/v1.0/myorg/gateways',
      { headers: { 'Authorization': `Bearer ${token}` } }
    );
    
    for (const gateway of gateways.value) {
      if (gateway.publicKey === null) {
        await sendAlert(`Gateway ${gateway.name} is offline!`);
      }
    }

    Costs

    ComponentCost
    Power BI Pro$10/User/Month
    Power BI PremiumFrom $4,995/Month
    n8n CloudFrom $20/Month
    Make.comFrom $9/Month

    Conclusion

    Power BI automation enables:

    • Real-time data updates
    • Automatic report distribution
    • Proactive KPI monitoring
    • Integration with other systems

    Next Steps

  • Register Azure AD App
  • Test Power BI API
  • Create first refresh workflow
  • Set up alerts
  • Automate report distribution
  • We can help you with Power BI automation, from setup to production use. Contact us for a free consultation. For more on connecting business systems, see our guide on API integration explained.