Skip to main content

ssrs powerbi library

A Python library for automating Power BI Report Server (PBIRS) and SQL Server Reporting Services (SSRS) via the REST API v2.0. Designed to replace PowerShell ReportingServicesTools in CI/CD pipelines.

Repository: ipierre1/ssrs-powerbi-library


Features

  • Easy API — connect once, get resource handle objects, call methods on them
  • NTLM authentication — native Windows/domain credentials via requests-ntlm
  • Power BI reports — upload, delete, data sources, data model parameters, cache refresh plans, security
  • Paginated (SSRS) reports — upload, delete, data sources, report parameters, cache refresh plans, security
  • Folder management — create, list, delete, security policies
  • Schedule helpers — build daily / weekly / monthly schedules with a fluent API
  • Row-level security — manage RLS role assignments on Power BI reports
  • Typed exceptions — PBIRSNotFound, PBIRSConflict, PBIRSAuthError
  • CI/CD ready — works in GitLab, GitHub Actions, Azure Pipelines, etc.

Installation

pip install ssrs-powerbi-library

Or from source:

git clone https://github.com/ipierre1/ssrs-powerbi-library.git
cd ssrs-powerbi-library
pip install -e .

Requirements: Python 3.8+, network access to PBIRS, NTLM-capable credentials.


Quick start

from ssrs_library import PBIRSClient

client = PBIRSClient(
    base_url="http://pbirs.corp.local/reports",
    username="svc_deploy",
    password="secret",
    domain="CORP",
)

client.test_connection()   # raises PBIRSAuthError / PBIRSError on failure

# Upload a .pbix
report = client.upload_powerbi_report(
    folder_path="/Sales",
    file_path="/ci/artifacts/Revenue.pbix",
    name="Revenue",
    overwrite=True,
)
print(report)  # <PowerBIReport name='Revenue' path='/Sales/Revenue'>

API reference

PBIRSClient

PBIRSClient(base_url, username, password, domain="", verify_ssl=True, timeout=30)
Method Returns Description
test_connection() bool Verify credentials & connectivity
get_folder(path) Folder Fetch a folder by catalog path
create_folder(path, description="") Folder Create folder (and intermediate folders)
list_folders(parent_path=None) List[Folder] List sub-folders
get_powerbi_report(path) PowerBIReport Fetch a .pbix report
list_powerbi_reports(folder_path=None) List[PowerBIReport] List .pbix reports
upload_powerbi_report(folder_path, file_path, name, overwrite=False) PowerBIReport Upload .pbix (auto-selects multipart for files >25 MB)
get_paginated_report(path) PaginatedReport Fetch a .rdl report
list_paginated_reports(folder_path=None) List[PaginatedReport] List .rdl reports
upload_paginated_report(folder_path, file_path, name, overwrite=False) PaginatedReport Upload .rdl

PowerBIReport

Obtained from client.get_powerbi_report(path) or client.upload_powerbi_report(...).

Properties

Property Type Description
id str Catalog GUID
name str Display name
path str Full catalog path
description str Description (empty string if absent)
has_data_sources bool Whether the report has bound data sources

Lifecycle

report.delete()

Data sources

sources = report.get_datasources()          # List[DataSource]
report.set_datasources([ds1, ds2])          # full replace

Data model parameters

params = report.get_data_model_parameters()
report.set_data_model_parameters([
    {"Name": "Environment", "Value": "Production"},
    {"Name": "MaxRows",     "Value": "10000"},
])

Cache refresh plans

plans = report.get_cache_refresh_plans()    # List[CacheRefreshPlan]

plan = report.create_cache_refresh_plan(
    description="Nightly refresh",
    schedule=Schedule.daily(hour=2),
)

Catalog security (who can view/edit the report)

policies = report.get_policies()
# {"InheritParentSecurity": False, "Policies": [...]}

report.set_policies(policies)               # full overwrite

report.add_user("CORP\\alice", ["Browser"])
report.add_user("CORP\\admins", ["Content Manager"])
report.remove_user("CORP\\alice")

Built-in role names: "Browser", "Content Manager", "Publisher", "Report Builder".

Row-level security (data model RLS)

roles = report.get_data_model_roles()       # model role definitions
assignments = report.get_data_model_role_assignments()

report.set_data_model_role_assignments([
    {"GroupUserName": "CORP\\alice", "Roles": ["Region_West"]},
    {"GroupUserName": "CORP\\bob",   "Roles": ["Region_East"]},
])

# Convenience helpers (read-modify-write):
report.add_rls_user("CORP\\alice", ["Region_West", "Region_North"])
report.remove_rls_user("CORP\\alice")

PaginatedReport

Obtained from client.get_paginated_report(path) or client.upload_paginated_report(...).

Same properties as PowerBIReport. Additional methods:

Method Description
delete() Delete from catalog
get_datasources() / set_datasources(datasources) Manage data sources
get_parameters() / set_parameters(params) Read / update report parameter definitions
get_cache_refresh_plans() List cache refresh plans
create_cache_refresh_plan(description, schedule, event_type) Create a cache refresh plan
get_policies() / set_policies(policy_data) Read / replace catalog security policies
add_user(username, roles) Grant catalog access (read-modify-write)
remove_user(username) Revoke catalog access (read-modify-write)

Folder

Obtained from client.get_folder(path) or client.create_folder(path).

Method Description
list_items() Raw catalog items (all types)
list_powerbi_reports() List[PowerBIReport] in this folder
list_paginated_reports() List[PaginatedReport] in this folder
list_folders() Sub-folders
delete() Delete folder and all contents
get_policies() / set_policies(policy_data) Read / replace security policies
add_user(username, roles) Grant access (read-modify-write)
remove_user(username) Revoke access (read-modify-write)

DataSource

from ssrs_library import DataSource

# SQL, integrated auth (default)
ds = DataSource("SalesDB", "Server=sql01;Database=Sales;")

# Stored credentials
ds = DataSource(
    name="SalesDB",
    connection_string="Server=sql01;Database=Sales;",
    credential_retrieval="Store",
    username="svc_report",
    password="secret",
    windows_credentials=False,
)

report.set_datasources([ds])
Parameter Default Description
name — Data source name
connection_string — ADO.NET connection string
data_source_type "SQL" Provider type (e.g. "Oracle", "OLEDB")
enabled True Whether the data source is active
id None GUID (set when reading from server)
description None Optional description
credential_retrieval "None" "None", "Integrated", or "Store"
username None Username for "Store" retrieval
password None Password for "Store" retrieval
windows_credentials True Use Windows auth for stored creds

Schedule

Helper for building cache-refresh plan schedules.

from ssrs_library import Schedule

# Daily at 02:00 (default)
Schedule.daily()

# Daily at 06:30
Schedule.daily(hour=6, minute=30)

# Every 3 days at 04:00
Schedule.daily(hour=4, interval=3)

# Every Monday and Friday at 08:30
Schedule.weekly(["Monday", "Friday"], hour=8, minute=30)

# Every two weeks on Wednesday
Schedule.weekly(["Wednesday"], interval=2)

# 1st of every month at 03:00 (default)
Schedule.monthly()

# 15th of January and July at 01:00
Schedule.monthly(day=15, months=["January", "July"], hour=1)

Pass a Schedule instance (or a raw {"Definition": {...}} dict) to create_cache_refresh_plan() or plan.update().


CacheRefreshPlan

Obtained from report.get_cache_refresh_plans() or report.create_cache_refresh_plan(...).

Method Description
execute() Trigger an immediate refresh
update(description=None, schedule=None) Modify description and/or schedule
delete() Delete this plan
plan.update(
    description="Updated nightly refresh",
    schedule=Schedule.daily(hour=3),
)

plan.execute()
plan.delete()

Exceptions

from ssrs_library import PBIRSError, PBIRSNotFound, PBIRSConflict, PBIRSAuthError
Exception Raised when
PBIRSAuthError HTTP 401 or 403
PBIRSNotFound HTTP 404
PBIRSConflict HTTP 409 (item already exists)
PBIRSError Any other HTTP error

Configuration patterns

Direct (script / notebook)

from ssrs_library import PBIRSClient

client = PBIRSClient(
    base_url="http://pbirs.corp.local/reports",
    username="alice",
    password="secret",
    domain="CORP",
)

Environment variables (CI/CD)

import os
from ssrs_library import PBIRSClient

client = PBIRSClient(
    base_url=os.environ["PBIRS_URL"],
    username=os.environ["PBIRS_USER"],
    password=os.environ["PBIRS_PASSWORD"],
    domain=os.environ.get("PBIRS_DOMAIN", ""),
)

.env file (local development)

from dotenv import load_dotenv
import os
from ssrs_library import PBIRSClient

load_dotenv()
client = PBIRSClient(
    base_url=os.environ["PBIRS_URL"],
    username=os.environ["PBIRS_USER"],
    password=os.environ["PBIRS_PASSWORD"],
    domain=os.environ.get("PBIRS_DOMAIN", ""),
)

CI/CD deploy example

from ssrs_library import PBIRSClient, DataSource, Schedule, PBIRSConflict
import os

client = PBIRSClient(
    base_url=os.environ["PBIRS_URL"],
    username=os.environ["PBIRS_USER"],
    password=os.environ["PBIRS_PASSWORD"],
    domain=os.environ.get("PBIRS_DOMAIN", ""),
)

# Ensure folder exists
try:
    folder = client.create_folder("/Sales")
except PBIRSConflict:
    folder = client.get_folder("/Sales")

# Deploy report
report = client.upload_powerbi_report(
    folder_path="/Sales",
    file_path="artifacts/Revenue.pbix",
    name="Revenue",
    overwrite=True,
)

# Point at production database
report.set_datasources([
    DataSource(
        "SalesDB",
        f"Server={os.environ['DB_HOST']};Database=Sales;",
        credential_retrieval="Store",
        username=os.environ["DB_USER"],
        password=os.environ["DB_PASSWORD"],
        windows_credentials=False,
    )
])

# Schedule nightly refresh at 02:00
for plan in report.get_cache_refresh_plans():
    plan.delete()

report.create_cache_refresh_plan(
    description="Nightly",
    schedule=Schedule.daily(hour=2),
)

# Grant read access
report.add_user("CORP\\Sales Team", ["Browser"])

Testing

pip install pytest
pytest tests/ -v

All tests use unittest.mock, no live server required.


License

MIT License

Metadata

Release files for ssrs-powerbi-library 1.2.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ssrs-powerbi-library 1.2.6
File Size Uploaded
ssrs_powerbi_library-1.2.6.tar.gz 33.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ssrs-powerbi-library 1.2.6
File Interpreter ABI Platform
ssrs_powerbi_library-1.2.6-py3-none-any.whl Python 3 none any Details

Total release size: 57.2 kB

Release files / ssrs_powerbi_library-1.2.6.tar.gz

Download URL ssrs_powerbi_library-1.2.6.tar.gz
Size 33.7 kB
Tags Source
SHA-256 checksum
How to use checksums
c1ea715ef97964f93b7db518f267ff4e00d0b95138d0ac8a8a7d6926b1c580ce
BLAKE2b-256 checksum
How to use checksums
6b7e566ba5efa61c6cef577733e092db0aa6317bcb89e11ad2c60fd9fbaad0d8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 1, 2026.

Transparency log

Release files / ssrs_powerbi_library-1.2.6-py3-none-any.whl

Download URL ssrs_powerbi_library-1.2.6-py3-none-any.whl
Size 23.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
dbe1a99c5553897597624ec4abf1164eba1dee179df18565b49a4e90c5ae17f4
BLAKE2b-256 checksum
How to use checksums
970c40b0cf8ed4aca1997fc89dd9fb8409c2cd9e6450b40edefe0635f5e132b7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 1, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.2.6 This release

2 release files

1.2.5

2 release files

1.2.4

2 release files

1.2.3

2 release files

1.2.2

2 release files

1.2.1

2 release files

1.2.0

2 release files

1.1.1

2 release files

1.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page