### Install Async Client Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Install the async client along with its required dependency 'aiohttp'. ```bash pip install "PowerPlatform-Dataverse-Client[async]" ``` -------------------------------- ### Install SDK and Dependencies for Testing Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/examples/README.md Installs the PowerPlatform Dataverse Client SDK and Azure Identity library using pip. This command is part of the initial setup for testing basic functionality. ```bash # Install the SDK and dependencies pip install PowerPlatform-Dataverse-Client azure-identity ``` -------------------------------- ### Install Dataverse Client from Source Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Clone the repository and install the Dataverse Client in editable mode for development. ```bash git clone https://github.com/microsoft/PowerPlatform-DataverseClient-Python.git cd PowerPlatform-DataverseClient-Python pip install -e . ``` -------------------------------- ### Install PowerPlatform Dataverse Client SDK Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/examples/README.md Installs the PowerPlatform Dataverse Client SDK and its dependencies using pip. This is the first step for validating the installation. ```bash pip install PowerPlatform-Dataverse-Client ``` -------------------------------- ### Install Async Client Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/CHANGELOG.md Install the library with async support using pip. This enables the use of AsyncDataverseClient. ```bash pip install PowerPlatform-Dataverse-Client[async] ``` -------------------------------- ### Install Dataverse Client Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Install the latest stable release of the PowerPlatform Dataverse Client using pip. ```bash # Install the latest stable release pip install PowerPlatform-Dataverse-Client ``` -------------------------------- ### Install Dataverse Client and Claude Skill Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Optionally install the Claude Skill globally along with the Dataverse Client. ```bash pip install PowerPlatform-Dataverse-Client && dataverse-install-claude-skill ``` -------------------------------- ### Install Migration Tool Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/CHANGELOG.md Install the migration tool with the optional extra dependency. This tool helps rewrite v0 call sites to the v1 API. ```bash pip install PowerPlatform-Dataverse-Client[migration] ``` -------------------------------- ### Validate Installation and Imports Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/examples/README.md Runs a Python script to validate the installation of the PowerPlatform Dataverse Client SDK, check method availability, and verify basic usage patterns. Useful for first-run validation after installation. ```python python examples/basic/installation_example.py ``` -------------------------------- ### Quick Start: Connect and Perform Basic Operations Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Demonstrates how to connect to Dataverse using interactive browser authentication, create, read, and delete a contact record. ```python from azure.identity import InteractiveBrowserCredential from PowerPlatform.Dataverse.client import DataverseClient # Connect to Dataverse credential = InteractiveBrowserCredential() with DataverseClient("https://yourorg.crm.dynamics.com", credential) as client: # Create a contact contact_id = client.records.create("contact", {"firstname": "John", "lastname": "Doe"}) # Read the contact back contact = client.records.retrieve("contact", contact_id, select=["firstname", "lastname"]) print(f"Created: {contact['firstname']} {contact['lastname']}") # Clean up client.records.delete("contact", contact_id) # Session closed, caches cleared automatically ``` -------------------------------- ### Async Quick Start: Create, Read, Update, Delete Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Demonstrates connecting to Dataverse asynchronously, creating a contact, retrieving it, and then cleaning up. Assumes `credential` is already constructed. ```python import asyncio from azure.identity import InteractiveBrowserCredential from PowerPlatform.Dataverse.aio import AsyncDataverseClient async def main(): # Connect to Dataverse credential = InteractiveBrowserCredential() async with DefaultAzureCredential() as credential: async with AsyncDataverseClient("https://yourorg.crm.dynamics.com", credential) as client: # Create a contact contact_id = await client.records.create("contact", {"firstname": "John", "lastname": "Doe"}) # Read it back contact = await client.records.retrieve("contact", contact_id, select=["firstname", "lastname"]) print(f"Created: {contact['firstname']} {contact['lastname']}") # Clean up await client.records.delete("contact", contact_id) asyncio.run(main()) ``` -------------------------------- ### Import Necessary Libraries Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md Imports the required authentication and Dataverse client classes. Ensure these libraries are installed. ```python from azure.identity import ( InteractiveBrowserCredential, ClientSecretCredential, CertificateCredential, AzureCliCredential ) from PowerPlatform.Dataverse.client import DataverseClient ``` -------------------------------- ### Import Async Client Libraries Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md Import necessary libraries for asynchronous operations with Dataverse. Ensure the '[async]' extra is installed for the SDK. ```python from azure.identity.aio import DefaultAzureCredential from PowerPlatform.Dataverse.aio import AsyncDataverseClient ``` -------------------------------- ### Get and List Tables Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md Retrieves information for a single Dataverse table by its logical name or lists all tables in the environment. ```python # Get single table information table_info = client.tables.get("new_Product") print(f"Logical name: {table_info['table_logical_name']}") print(f"Entity set: {table_info['entity_set_name']}") # List all tables tables = client.tables.list() for table in tables: print(table) ``` -------------------------------- ### Set Up Alternate Key for Upsert Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md This one-time setup creates an alternate key for the 'account' table using the 'accountnumber' field, which is a prerequisite for using upsert operations with this key. ```python # One-time setup for the examples below: make accountnumber an alternate key on account key = client.tables.create_alternate_key( "account", "account_accountnumber_ak", ["accountnumber"], display_name="Account Number", ) print(f"Created key {key.schema_name} ({key.metadata_id}), status={key.status}") # Optional: check key status (useful right after creation; status transitions Pending -> Active) for k in client.tables.get_alternate_keys("account"): if k.schema_name == "account_accountnumber_ak": print(f"{k.schema_name}: {k.status}") ``` -------------------------------- ### End-to-End SQL Query Examples Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/examples/README.md Executes a Python script showcasing end-to-end SQL query capabilities with the Dataverse SDK, including schema discovery, various SQL clauses, JOINs, pagination, and SQL to DataFrame transformations. Includes SDK fallbacks for unsupported SQL operations. ```python python examples/advanced/sql_examples.py ``` -------------------------------- ### Correct Docstring Type Annotations Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-dev/SKILL.md Examples of correctly formatted type annotations for Dataverse SDK docstrings compatible with Microsoft Learn. ```rst :type data: dict or list[dict] :rtype: list[str] :rtype: collections.abc.Iterable[list[~PowerPlatform.Dataverse.models.record.Record]] :type select: list[str] or None :type columns: dict[str, typing.Any] ``` -------------------------------- ### Basic CRUD Operations for Accounts Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Illustrates creating, reading, updating, and deleting account records. Includes an example of reading a record with an expanded related primary contact. ```python # Create a record account_id = client.records.create("account", {"name": "Contoso Ltd"}) # Read a record account = client.records.retrieve("account", account_id) print(account["name"]) # Read with expand — fetch a related record in the same HTTP request account = client.records.retrieve( "account", account_id, select=["name"], expand=["primarycontactid"], ) contact = (account.get("primarycontactid") or {}) print(contact.get("fullname")) # Update a record client.records.update("account", account_id, {"telephone1": "555-0199"}) # Delete a record client.records.delete("account", account_id) ``` -------------------------------- ### Create Records with Lookup Bindings Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md Demonstrates how to create new records in Dataverse and set lookup fields using the '@odata.bind' annotation. It highlights the correct usage of PascalCase navigation property names and provides an example of an incorrect usage that leads to an error. ```APIDOC ## Create Records with Lookup Bindings (@odata.bind) ### Description Creates new records and sets lookup fields using the `@odata.bind` annotation. Ensure to use the correct PascalCase navigation property name as defined in the `$metadata`. ### Method `client.records.create(table_name, record_data)` ### Parameters - `table_name` (string): The name of the Dataverse table. - `record_data` (dict): A dictionary containing the record's fields. Lookup fields should use the format `NavigationPropertyName@odata.bind`: `/TableName(RecordId)`. ### Request Example ```python # Set lookup fields using @odata.bind with PascalCase navigation property names guid = client.records.create("new_ticket", { "new_name": "TKT-001", "new_CustomerId@odata.bind": f"/new_customers({customer_id})", "new_AgentId@odata.bind": f"/new_agents({agent_id})", }) ``` ``` -------------------------------- ### Build and Execute a Dataverse Batch Request Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md Construct a batch request with various operations like create, update, retrieve, list, and SQL query. Execute the batch and iterate through the responses to check for success or errors. Results for GET operations are available in `item.data`. ```python # Build a batch request batch = client.batch.new() batch.records.create("account", {"name": "Contoso"}) batch.records.update("account", account_id, {"telephone1": "555-0100"}) batch.records.retrieve("account", account_id, select=["name"], expand=["primarycontactid"], include_annotations="OData.Community.Display.V1.FormattedValue") # single record with expand batch.records.list("account", filter="statecode eq 0", select=["name"], orderby=["name asc"], top=50, page_size=25, count=True) # multi-record, single page batch.query.sql("SELECT TOP 5 name FROM account") result = batch.execute() for item in result.responses: if item.is_success: print(f"[OK] {item.status_code} entity_id={item.entity_id}") if item.data: # GET responses populate item.data with the parsed JSON record print(item.data.get("name")) else: print(f"[ERR] {item.status_code}: {item.error_message}") ``` -------------------------------- ### Sample HTTP Request and Response Log Output Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Example of captured HTTP request and response logs, showing redacted authorization headers and request/response details. Useful for debugging API interactions. ```log [2026-04-11T15:27:31-0700] DEBUG >>> REQUEST POST https://yourorg.crm.dynamics.com/api/data/v9.2/accounts Authorization: [REDACTED] Accept: application/json Content-Type: application/json OData-MaxVersion: 4.0 OData-Version: 4.0 User-Agent: DataverseSvcPythonClient:0.1.0b8 x-ms-client-request-id: 7050c4d0-6bcc-48e3-a310-b4e8fa18ac69 x-ms-correlation-id: 4cace77d-e4ee-4419-8c65-fc62beed6e71 Body: {"name":"Contoso Ltd"} [2026-04-11T15:27:31-0700] DEBUG <<< RESPONSE 204 POST https://yourorg.crm.dynamics.com/api/data/v9.2/accounts (78.0ms) Content-Type: application/json; odata.metadata=minimal OData-Version: 4.0 x-ms-service-request-id: a6d0b6c4-5dd1-47cb-83eb-b6fccf754216 x-ms-ratelimit-burst-remaining-xrm-requests: 7998 ``` -------------------------------- ### Batch Operations for Table Metadata and SQL Queries Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Include operations for managing table metadata (create, add columns, get) and executing SQL queries within a single batch request. This allows for efficient bulk management and data retrieval. ```python batch = client.batch.new() batch.tables.create("new_Product", {"new_Price": "decimal", "new_InStock": "bool"}) batch.tables.add_columns("new_Product", {"new_Rating": "int"}) batch.tables.get("new_Product") batch.query.sql("SELECT TOP 5 name FROM account") result = batch.execute() ``` -------------------------------- ### Create Records from DataFrame Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md Create new records in Dataverse by passing a pandas DataFrame to the `client.dataframe.create` method. The method returns a Series of the newly created record GUIDs. ```python # Create records from a DataFrame (returns a Series of GUIDs) new_accounts = pd.DataFrame([ {"name": "Contoso", "telephone1": "555-0100"}, {"name": "Fabrikam", "telephone1": "555-0200"}, ]) new_accounts["accountid"] = client.dataframe.create("account", new_accounts) ``` -------------------------------- ### Deprecated DataverseClient Methods Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/CHANGELOG.md Calls to flat methods on `DataverseClient` (e.g., `create`, `update`, `delete`, `get`, `query_sql`, `upload_file`) will now emit a `DeprecationWarning` and delegate to the corresponding namespaced operations. ```python client.create() ``` ```python client.update() ``` ```python client.delete() ``` ```python client.get() ``` ```python client.query_sql() ``` ```python client.upload_file() ``` -------------------------------- ### Fluent Query Builder for Records Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Use the recommended fluent QueryBuilder to construct OData queries. It automatically handles value formatting, column casing, and syntax. This example iterates through paged results. ```python # Fluent query builder (recommended) from PowerPlatform.Dataverse.models.filters import col for record in (client.query.builder("account") .select("name", "revenue") .where(col("statecode") == 0) .where(col("revenue") > 1000000) .order_by("revenue", descending=True) .top(100) .page_size(50) .execute()): print(f"{record['name']}: {record['revenue']}") ``` -------------------------------- ### Sphinx Directive Example Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/CONTRIBUTING.md Example of a docstring directive that causes a broken cross-reference on Microsoft Learn. ```rst :rtype: :class:`list` of :class:`str` ``` -------------------------------- ### Initialize Dataverse Client Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md Shows how to initialize the Dataverse client using different authentication methods. Using a context manager is recommended for automatic resource management. ```python # Development options credential = InteractiveBrowserCredential() credential = AzureCliCredential() # Production options credential = ClientSecretCredential(tenant_id, client_id, client_secret) credential = CertificateCredential(tenant_id, client_id, cert_path) # Create client with context manager (recommended -- enables HTTP connection pooling) # No trailing slash on URL! with DataverseClient("https://yourorg.crm.dynamics.com", credential) as client: ... # all operations here # Session closed, caches cleared automatically # Or without context manager: client = DataverseClient("https://yourorg.crm.dynamics.com", credential) ``` -------------------------------- ### Comprehensive Dataverse SDK Walkthrough Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/examples/README.md Runs a Python script demonstrating comprehensive SDK features with production-ready patterns, including advanced querying, metadata management, and error handling. Recommended for mastering advanced features. ```python python examples/advanced/walkthrough.py ``` -------------------------------- ### Delete Records using DataFrame GUIDs Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md Delete Dataverse records by providing a pandas Series containing their GUIDs to the `client.dataframe.delete` method. ```python # Delete records by passing a Series of GUIDs client.dataframe.delete("account", new_accounts["accountid"]) ``` -------------------------------- ### Get Record Count via Query Builder Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Include `$count=true` in the request using the query builder to retrieve the total count of matching records. The `QueryResult` object is sized, so use `len()` to get the count. ```python # Via query builder results = ( client.query.builder("account") .where(col("statecode") == 0) .count() .execute() ) print(len(results)) # QueryResult is sized — use len() to get the count ``` -------------------------------- ### Client Initialization Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md Demonstrates how to initialize the DataverseClient using different credential types for development and production environments. It also shows how to use the client with a context manager for automatic resource management. ```APIDOC ## Client Initialization ### Description Initialize the Dataverse client with appropriate credentials. Supports interactive browser, Azure CLI, client secret, and certificate-based authentication. ### Usage ```python from azure.identity import ( InteractiveBrowserCredential, ClientSecretCredential, CertificateCredential, AzureCliCredential ) from PowerPlatform.Dataverse.client import DataverseClient # Development options credential = InteractiveBrowserCredential() credential = AzureCliCredential() # Production options credential = ClientSecretCredential(tenant_id, client_id, client_secret) credential = CertificateCredential(tenant_id, client_id, cert_path) # Create client with context manager (recommended -- enables HTTP connection pooling) # No trailing slash on URL! with DataverseClient("https://yourorg.crm.dynamics.com", credential) as client: # ... all operations here # Session closed, caches cleared automatically # Or without context manager: client = DataverseClient("https://yourorg.crm.dynamics.com", credential) ``` ``` -------------------------------- ### Get Relationship Metadata Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Retrieves the metadata for a specific relationship by its schema name. ```APIDOC ## Get Relationship Metadata ### Description Retrieves the metadata for a specific relationship using its schema name. ### Method `client.tables.get_relationship(relationship_schema_name)` ### Parameters #### Path Parameters - **relationship_schema_name** (string) - Required - The schema name of the relationship to retrieve. ### Response #### Success Response (200) - **relationship_schema_name** (string) - The schema name of the relationship. - **relationship_type** (string) - The type of the relationship (e.g., OneToMany, ManyToMany). ### Response Example ```python rel = client.tables.get_relationship("new_Department_Employee") if rel: print(f"Found: {rel.relationship_schema_name}") ``` ``` -------------------------------- ### Incorrect Docstring Annotation Patterns Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/CONTRIBUTING.md Examples of patterns that should be avoided to prevent broken documentation links. ```rst :type data: :class:`dict` or :class:`list` of :class:`dict` :rtype: :class:`list` of :class:`str` ``` -------------------------------- ### Run Migration Tool Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/CHANGELOG.md Execute the dataverse-migrate console script to rewrite v0 call sites. Use --dry-run to preview changes without modifying files. ```bash dataverse-migrate --dry-run . ``` -------------------------------- ### Async Dataverse Client Initialization Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md Initialize the asynchronous Dataverse client. The recommended approach uses a context manager to automatically handle session closure and cache clearing. Alternatively, manual initialization requires explicit closing in a finally block. ```python # given: credential constructed (e.g. DefaultAzureCredential()) # Context manager (recommended -- closes session and clears caches automatically) async with AsyncDataverseClient("https://yourorg.crm.dynamics.com", credential) as client: ... # all operations here # Standalone (call aclose() in a finally block) client = AsyncDataverseClient("https://yourorg.crm.dynamics.com", credential) try: ... finally: await client.aclose() ``` -------------------------------- ### Get Relationship Information Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/CHANGELOG.md Retrieve details about an existing relationship between Dataverse tables using the `get_relationship` method. ```python client.get_relationship() ``` -------------------------------- ### Update Records Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md Provides examples for updating single records and performing bulk updates on multiple records with the same change. ```APIDOC ## Update Records ### Description Updates existing records in Dataverse. Supports updating a single record by its ID or performing a bulk update to apply the same change to multiple records. ### Method `client.records.update(table_name, record_id_or_ids, record_data)` ### Parameters - `table_name` (string): The name of the Dataverse table. - `record_id_or_ids` (string or list): The ID of the record to update, or a list of IDs for bulk update. - `record_data` (dict): A dictionary containing the fields to update. ### Request Example ```python # Single update client.records.update("account", account_id, {"telephone1": "555-0200"}) # Bulk update (broadcast same change to multiple records) client.records.update("account", [id1, id2, id3], {"industry": "Technology"}) ``` ``` -------------------------------- ### Create Table with Custom Primary Column and Solution Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Illustrates creating a custom table with a specified primary column name and assigning it to a specific solution. ```python # Create with custom primary column name and solution assignment table_info = client.tables.create( "new_Product", columns={ "new_Code": "string", "new_Price": "decimal" }, solution="MyPublisher", # Optional: add to specific solution primary_column="new_ProductName", # Optional: custom primary column (default is "{customization prefix value}_Name") ) ``` -------------------------------- ### Incorrect Docstring Type Annotations Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-dev/SKILL.md Examples of incorrectly formatted type annotations that will cause broken cross-references on Microsoft Learn. ```rst :type data: :class:`dict` or :class:`list` of :class:`dict` :rtype: :class:`list` of :class:`str` :type columns: :class:`dict` mapping :class:`str` to :class:`typing.Any` ``` -------------------------------- ### FetchXML Queries Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md Demonstrates how to execute FetchXML queries against Dataverse. It shows how to load all results into memory or stream results page by page. ```APIDOC ## FetchXML Queries `client.query.fetchxml(xml)` returns an inert `FetchXmlQuery` object. HTTP requests are made only when `.execute()` or `.execute_pages()` is called. ### Example Usage ```python xml = """ """ # Load all results into memory query = client.query.fetchxml(xml) result = query.execute() for record in result: print(record["name"]) # Stream results page-by-page for page in query.execute_pages(): process(page.to_dataframe()) ``` ``` -------------------------------- ### Get Table Information Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Retrieves metadata for a specific Dataverse table, including its logical name and entity set name. ```python # Get table information info = client.tables.get("new_Product") print(f"Logical name: {info['table_logical_name']}") print(f"Entity set: {info['entity_set_name']}") ``` -------------------------------- ### Get Alternate Keys for a Table Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/CHANGELOG.md Retrieve existing alternate keys for a specified Dataverse table using the `get_alternate_keys` method. ```python client.tables.get_alternate_keys() ``` -------------------------------- ### Performing Batch Operations Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md Demonstrates how to build and execute a batch request, including creating, updating, retrieving, and listing records, as well as executing SQL queries. It also shows how to process the results and handle potential errors. ```APIDOC ## Batch Operations Use `client.batch` to send multiple operations in one HTTP request. All batch methods return `None`; results arrive via `BatchResult` after `execute()`. ```python # Build a batch request batch = client.batch.new() batch.records.create("account", {"name": "Contoso"}) batch.records.update("account", account_id, {"telephone1": "555-0100"}) batch.records.retrieve("account", account_id, select=["name"], expand=["primarycontactid"], include_annotations="OData.Community.Display.V1.FormattedValue") # single record with expand batch.records.list("account", filter="statecode eq 0", select=["name"], orderby=["name asc"], top=50, page_size=25, count=True) # multi-record, single page batch.query.sql("SELECT TOP 5 name FROM account") result = batch.execute() for item in result.responses: if item.is_success: print(f"[OK] {item.status_code} entity_id={item.entity_id}") if item.data: # GET responses populate item.data with the parsed JSON record print(item.data.get("name")) else: print(f"[ERR] {item.status_code}: {item.error_message}") # Transactional changeset (all succeed or roll back) with batch.changeset() as cs: ref = cs.records.create("contact", {"firstname": "Alice"}) cs.records.update("account", account_id, {"primarycontactid@odata.bind": ref}) # Continue on error result = batch.execute(continue_on_error=True) print(f"Succeeded: {len(result.succeeded)}, Failed: {len(result.failed)}") ``` **BatchResult properties:** - `result.responses` -- list of `BatchItemResponse` in submission order - `result.succeeded` -- responses with 2xx status codes - `result.failed` -- responses with non-2xx status codes - `result.has_errors` -- True if any response failed - `result.entity_ids` -- GUIDs from OData-EntityId headers (creates and updates) **Batch limitations:** - Maximum 1000 operations per batch - `batch.records.get()` is deprecated; use `batch.records.retrieve()` for single records - `batch.records.list()` returns a single page (no pagination); use `top` to bound results - `flush_cache()` is not supported in batch ``` -------------------------------- ### Execute SQL Queries Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Shows how to execute SQL queries against Dataverse. Supports JOINs, aggregates, GROUP BY, DISTINCT, and OFFSET FETCH pagination. Results can be directly converted to a DataFrame. ```python # Basic query results = client.query.sql( "SELECT TOP 10 accountid, name FROM account WHERE statecode = 0" ) # JOINs and aggregates work results = client.query.sql( "SELECT a.name, COUNT(c.contactid) as cnt " "FROM account a " "JOIN contact c ON a.accountid = c.parentcustomerid " "GROUP BY a.name" ) # SQL results directly as a DataFrame df = client.dataframe.sql( "SELECT name, revenue FROM account ORDER BY revenue DESC" ) # Discover columns from metadata (schema-discovery helper, kept at GA) cols_meta = client.query.sql_columns("account") col_names = [c["LogicalName"] for c in cols_meta] # Build queries using the discovered column names sql = f"SELECT TOP 10 {', '.join(col_names[:5])} FROM account" df = client.dataframe.sql(sql) ``` -------------------------------- ### Update Records from DataFrame Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Update existing Dataverse records using a pandas DataFrame. Specify the GUID column using `id_column`. ```python # Update records from a DataFrame (id_column identifies the GUID column) new_accounts["telephone1"] = ["555-0199", "555-0299"] client.dataframe.update("account", new_accounts, id_column="accountid") ``` -------------------------------- ### Expand Navigation Properties with Query Builder Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Demonstrates expanding navigation properties using the query builder. Requires importing ExpandOption. This allows fetching related entity data in a single query. ```python # Discover navigation property names for $expand (metadata-discovery helper, kept at GA) nav_props = client.query.odata_expands("account") # → list of navigation property metadata # Expand navigation properties using the query builder from PowerPlatform.Dataverse.models.query_builder import ExpandOption for record in (client.query.builder("contact") .select("fullname") .expand(ExpandOption("parentcustomerid_account").select("name")) .execute()): acct = record.get("parentcustomerid_account") or {} print(f"{record['fullname']} -> {acct.get('name')}") ``` -------------------------------- ### Query Builder: Convert Results to DataFrame Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md Converts query results directly into a pandas DataFrame for easier data manipulation and analysis. Requires pandas to be installed. ```python # Convert query results to a DataFrame df = ( client.query.builder("account") .select("accountid", "name") .where(col("statecode") == 0) .execute() .to_dataframe() ) ``` -------------------------------- ### Bulk Operations: Create, Update, and Delete Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Shows how to perform bulk create, update, and delete operations on account records. Bulk delete requires the `use_bulk_delete` parameter to be set to `True`. ```python # Bulk create payloads = [ {"name": "Company A"}, {"name": "Company B"}, {"name": "Company C"} ] ids = client.records.create("account", payloads) # Bulk update (broadcast same change to all) client.records.update("account", ids, {"exchangerate": 1}) # Bulk delete client.records.delete("account", ids, use_bulk_delete=True) ``` -------------------------------- ### Async Query Builder: Execute and Collect Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Demonstrates using the async query builder to select specific columns, filter records, and retrieve the top 10 results. ```python # given: client is an open AsyncDataverseClient from PowerPlatform.Dataverse.models.filters import col # Execute and collect all results result = await ( client.query.builder("account") .select("name", "telephone1") .where(col("statecode") == 0) .top(10) .execute() ) for record in result: print(record["name"]) ``` -------------------------------- ### Create a Custom Table Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Demonstrates creating a new custom table (entity) in Dataverse. Custom column names must include the customization prefix (e.g., 'new_'). ```python # Create a custom table, including the customization prefix value in the schema names for the table and columns. table_info = client.tables.create("new_Product", { "new_Code": "string", "new_Description": "memo", "new_Price": "decimal", "new_Active": "bool" }) ``` -------------------------------- ### Read Records Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md Provides examples for retrieving single records by ID, including fetching related records using expand, and listing records with basic filtering and selection. ```APIDOC ## Read Records ### Description Retrieve single records by ID or list multiple records with filtering and selection. Supports expanding related entities. ### Usage ```python # Get single record by ID account = client.records.retrieve("account", account_id, select=["name", "telephone1"]) # With expand — fetch a related record in the same HTTP request account = client.records.retrieve( "account", account_id, select=["name"], expand=["primarycontactid"], ) contact = (account.get("primarycontactid") or {}) print(contact.get("fullname")) # Simple shortcut — use records.list() only for basic filter + select without composable logic. # Follows @odata.nextLink automatically and loads all matching records into memory. # For filtering, sorting, expansion, or formatted values, prefer client.query.builder() (see below). result = client.records.list("account", filter="statecode eq 0", select=["name", "accountid"]) for record in result: print(record["name"]) ``` ``` -------------------------------- ### Async Batch Operations: Simple Batch Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Creates a new batch and adds two account creation operations to it, then executes the batch. ```python # given: client is open; account_id is the GUID returned by an earlier records.create batch = client.batch.new() batch.records.create("account", {"name": "Alpha"}) batch.records.create("account", {"name": "Beta"}) result = await batch.execute() print(f"Created {len(result.entity_ids)} records") ``` -------------------------------- ### List All Tables Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Fetches and prints a list of all tables (entities) available in the Dataverse environment. ```python # List all tables tables = client.tables.list() for table in tables: print(table) ``` -------------------------------- ### Create Custom Tables Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md Shows how to create new custom tables in Dataverse, with options for specifying columns, solution assignment, and custom primary columns. ```APIDOC ## Create Custom Tables ### Create table with columns ```python # Create table with columns (include customization prefix!) table_info = client.tables.create( "new_Product", { "new_Code": "string", "new_Price": "decimal", "new_Active": "bool", "new_Quantity": "int", }, ) ``` ### Create table with solution assignment and custom primary column ```python # With solution assignment and custom primary column table_info = client.tables.create( "new_Product", {"new_Code": "string", "new_Price": "decimal"}, solution="MyPublisher", primary_column="new_ProductCode", ) ``` ``` -------------------------------- ### Correct Docstring Annotation Patterns Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/CONTRIBUTING.md Recommended syntax for defining types and return types to ensure proper documentation rendering. ```rst :type data: dict or list[dict] :rtype: list[str] :type select: list[str] or None ``` -------------------------------- ### Execute FetchXML Queries Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Demonstrates executing FetchXML queries using the client. The .execute() method fetches all pages and returns a single QueryResult, while .execute_pages() streams results page by page. ```python xml = """ """ # .execute() — blocking, fetches all pages and returns a single QueryResult result = client.query.fetchxml(xml).execute() df = result.to_dataframe() # .execute_pages() — streaming, yields one QueryResult per HTTP page # Use count="N" in the FetchXML element to set page size for page_num, page in enumerate(client.query.fetchxml(xml).execute_pages()): print(f"Page {page_num + 1}: {len(page)} records") for record in page: print(record["name"]) ``` -------------------------------- ### Get Record Count via Records List Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Use `count=True` with `records.list()` to add `$count=true` to the OData request. The `len()` function on the result provides the total number of records fetched. ```python # Via records.list() — count=True adds $count=true to the OData request results = client.records.list("account", filter="statecode eq 0", count=True) print(len(results)) ``` -------------------------------- ### Create Single and Multiple Records Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md Demonstrates creating single records and using the bulk create API for multiple records. The SDK automatically uses CreateMultiple for lists. ```python # Single record account_id = client.records.create("account", {"name": "Contoso Ltd", "telephone1": "555-0100"}) # Bulk create (uses CreateMultiple API automatically) contacts = [ {"firstname": "John", "lastname": "Doe"}, {"firstname": "Jane", "lastname": "Smith"} ] contact_ids = client.records.create("contact", contacts) ``` -------------------------------- ### Streaming Shortcut via records.list_pages() Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md Provides a simpler way to stream results page-by-page using `records.list_pages()`, suitable for basic filter and select operations. ```python # Simple streaming shortcut via records.list_pages() (string filter only, same params as records.list()) for page in client.records.list_pages("account", filter="statecode eq 0", select=["name"], page_size=500): for record in page: print(record["name"]) ``` -------------------------------- ### Update Records from DataFrame Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md Update existing Dataverse records using data from a pandas DataFrame. Specify the `id_column` to identify the GUID column. Use `clear_nulls=True` to explicitly clear fields by setting them to null. ```python # Update records from a DataFrame (id_column identifies the GUID column) new_accounts["telephone1"] = ["555-0199", "555-0299"] client.dataframe.update("account", new_accounts, id_column="accountid") # Clear a field by setting clear_nulls=True (by default, NaN/None fields are skipped) df = pd.DataFrame([{"accountid": "guid-1", "websiteurl": None}]) client.dataframe.update("account", df, id_column="accountid", clear_nulls=True) ``` -------------------------------- ### File Operations Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md Demonstrates how to upload files to a file column in a Dataverse table. It also shows that the file column can be created automatically if it doesn't exist. ```APIDOC ## File Operations ```python # Upload file to a file column client.files.upload( table="account", record_id=account_id, file_column="new_Document", # If the file column doesn't exist, it will be created automatically path="/path/to/document.pdf", ) ``` ``` -------------------------------- ### Query, List, and Delete Relationships Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md This snippet demonstrates how to retrieve metadata for a specific relationship, list all relationships, list relationships for a particular table, and delete a relationship. ```python # Query relationship metadata rel = client.tables.get_relationship("new_Department_Employee") if rel: print(f"Found: {rel.relationship_schema_name}") # List all relationships rels = client.tables.list_relationships() for rel in rels: print(f"{rel['SchemaName']} ({rel.get('RelationshipType')})") # List relationships for a specific table (one-to-many + many-to-one + many-to-many) account_rels = client.tables.list_table_relationships("account") for rel in account_rels: print(f"{rel['SchemaName']} -> {rel.get('RelationshipType')}") # Delete a relationship client.tables.delete_relationship(result.relationship_id) ``` -------------------------------- ### Query Builder: Composable Filters (AND/OR/NOT) Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md Demonstrates building complex filters using Python's bitwise operators for AND, OR, and NOT conditions with the query builder. ```python # Composable filters — AND / OR / NOT using Python operators result = ( client.query.builder("contact") .select("fullname", "emailaddress1") .where((col("statecode") == 0) & (col("emailaddress1").contains("@contoso.com"))) .execute() ) ``` -------------------------------- ### Use Context Manager for Dataverse Client Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/CHANGELOG.md Utilize the `with` statement for automatic resource cleanup and connection pooling when interacting with the Dataverse client. This ensures proper lifecycle management. ```python with DataverseClient(...) as client: # Use client here ``` -------------------------------- ### FetchXML Queries Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Use `client.query.fetchxml()` to create an inert `FetchXmlQuery` object. An HTTP request is only made when `.execute()` or `.execute_pages()` is called. ```python # FetchXML queries -- client.query.fetchxml() returns an inert FetchXmlQuery object; no HTTP request is made until you call .execute() or .execute_pages(): ``` -------------------------------- ### Build and Execute a Batch Request Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Construct a batch request by adding various record operations (create, update, delete, retrieve, list) and then execute it. The results contain responses for each operation. ```python # Build a batch request and add operations batch = client.batch.new() batch.records.create("account", {"name": "Contoso"}) batch.records.create("account", [{"name": "Fabrikam"}, {"name": "Woodgrove"}]) batch.records.update("account", account_id, {"telephone1": "555-0100"}) batch.records.delete("account", old_id) batch.records.retrieve("account", account_id, select=["name"], expand=["primarycontactid"]) # single record with expand batch.records.list( # multi-record, single page "account", filter="statecode eq 0", select=["name"], orderby=["name asc"], top=50, ) result = batch.execute() for item in result.responses: if item.is_success: print(f"[OK] {item.status_code} entity_id={item.entity_id}") else: print(f"[ERR] {item.status_code}: {item.error_message}") ``` -------------------------------- ### Create Records with Lookup Bindings Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md Use @odata.bind to set lookup fields, ensuring PascalCase navigation property names match the $metadata. Incorrect casing will result in an ODataException. ```python # Set lookup fields using @odata.bind with PascalCase navigation property names # CORRECT: use the navigation property name (case-sensitive, must match $metadata) guid = client.records.create("new_ticket", { "new_name": "TKT-001", "new_CustomerId@odata.bind": f"/new_customers({customer_id})", "new_AgentId@odata.bind": f"/new_agents({agent_id})", }) # WRONG: lowercase navigation property causes 400 error # "new_customerid@odata.bind" -> ODataException: undeclared property 'new_customerid' ``` -------------------------------- ### Async Standalone Client Usage Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Shows how to use the `AsyncDataverseClient` without the `async with` statement, ensuring the client is properly closed afterwards. ```python # given: credential constructed as in Quick start (e.g. DefaultAzureCredential()) client = AsyncDataverseClient("https://yourorg.crm.dynamics.com", credential) try: account_id = await client.records.create("account", {"name": "Contoso Ltd"}) finally: await client.aclose() ``` -------------------------------- ### Async Batch Operations: Atomic Changeset Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Demonstrates creating an atomic changeset within a batch to create a contact and update an account, linking them via the primary contact. ```python # Atomic changeset batch = client.batch.new() async with batch.changeset() as cs: ref = cs.records.create("contact", {"firstname": "Alice"}) cs.records.update("account", account_id, {"primarycontactid@odata.bind": ref}) result = await batch.execute() ``` -------------------------------- ### Add Version Comparison Links to CHANGELOG.md Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/CONTRIBUTING.md After creating tags, add version comparison links at the bottom of CHANGELOG.md to facilitate navigation between release versions. ```markdown [0.1.0b3]: https://github.com/microsoft/PowerPlatform-DataverseClient-Python/compare/v0.1.0b2...v0.1.0b3 [0.1.0b2]: https://github.com/microsoft/PowerPlatform-DataverseClient-Python/compare/v0.1.0b1...v0.1.0b2 [0.1.0b1]: https://github.com/microsoft/PowerPlatform-DataverseClient-Python/releases/tag/v0.1.0b1 ``` -------------------------------- ### SQL Queries Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md Details how to execute read-only SQL queries against Dataverse, supporting limited SQL syntax including SELECT, WHERE, TOP, and ORDER BY. ```APIDOC ## SQL Queries ### Description Executes read-only SQL queries against Dataverse. Supports a limited subset of SQL syntax, including `SELECT`, `WHERE`, `TOP`, and `ORDER BY`. JOINs and subqueries are not supported. ### Method `client.query.sql(sql_query)` ### Parameters - `sql_query` (string): The SQL query string to execute. Must be a single SELECT statement. ### Request Example ```python results = client.query.sql( "SELECT TOP 10 accountid, name FROM account WHERE statecode = 0" ) for record in results: print(record["name"]) ``` ``` -------------------------------- ### Async Query Builder: Lazy Iteration Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Illustrates memory-efficient, page-by-page iteration over query results using the async query builder. ```python # Lazy page-by-page iteration (memory-efficient for large sets) async for page in ( client.query.builder("account") .select("name") .page_size(500) .execute_pages() ): for record in page: print(record["name"]) ``` -------------------------------- ### Create Alternate Key with Dataverse Client Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/CHANGELOG.md Manage alternate keys for Dataverse tables using the `create_alternate_key` method. This requires specifying the table name and the alternate key details. ```python client.tables.create_alternate_key() ``` -------------------------------- ### Create Annotated Git Tag for Release Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/CONTRIBUTING.md Use this command to create an annotated Git tag for a specific release version. Ensure the tag message clearly indicates the version. ```bash # Create annotated tag for version X.Y.Z git tag -a vX.Y.Z -m "Release vX.Y.Z" # Push tag to remote git push origin --tags ``` -------------------------------- ### Configure HTTP Diagnostics Logging Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/README.md Set up file-based HTTP logging to capture requests and responses. Configure the log folder, file prefix, and maximum body size to capture. Sensitive headers are automatically redacted. ```python from PowerPlatform.Dataverse.client import DataverseClient from PowerPlatform.Dataverse.core import DataverseConfig, LogConfig log_cfg = LogConfig( log_folder="./my_logs", # Directory for log files (created if missing) log_file_prefix="crm_debug", # Filename prefix; timestamp appended automatically max_body_bytes=4096, # Bytes of body to capture per entry — 0 (default) disables body capture ) config = DataverseConfig(log_config=log_cfg) client = DataverseClient("https://yourorg.crm.dynamics.com", credential, config=config) ``` -------------------------------- ### Execute FetchXML Query Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/CHANGELOG.md Use client.query.fetchxml to create an inert FetchXmlQuery object. The HTTP call is made only when .execute() or .execute_pages() is invoked. Supports advanced paging logic and URL limits. ```python client.query.fetchxml(xml) ``` -------------------------------- ### Create Records Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md Shows how to create single and multiple records in Dataverse using the SDK. The bulk create operation automatically utilizes the CreateMultiple API for efficiency. ```APIDOC ## Create Records ### Description Create single or multiple records in Dataverse. The `create` method handles both scenarios, using `CreateMultiple` API for lists. ### Usage ```python # Single record account_id = client.records.create("account", {"name": "Contoso Ltd", "telephone1": "555-0100"}) # Bulk create (uses CreateMultiple API automatically) contacts = [ {"firstname": "John", "lastname": "Doe"}, {"firstname": "Jane", "lastname": "Smith"} ] contact_ids = client.records.create("contact", contacts) ``` ``` -------------------------------- ### Inspect Tables Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md Demonstrates how to retrieve information about a specific table or list all tables within Dataverse. ```APIDOC ## Inspect Tables ### Get single table information ```python # Get single table information table_info = client.tables.get("new_Product") print(f"Logical name: {table_info['table_logical_name']}") print(f"Entity set: {table_info['entity_set_name']}") ``` ### List all tables ```python # List all tables tables = client.tables.list() for table in tables: print(table) ``` ``` -------------------------------- ### Handling Dataverse SDK Exceptions Source: https://github.com/microsoft/powerplatform-dataverseclient-python/blob/main/src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md Demonstrates how to catch and process specific Dataverse SDK exceptions like HttpError and ValidationError. Includes checking for transient errors and extracting detailed error information. ```python from PowerPlatform.Dataverse.core.errors import ( DataverseError, HttpError, MetadataError, SQLParseError, ValidationError, ) from PowerPlatform.Dataverse.client import DataverseClient try: client.records.retrieve("account", "invalid-id") except HttpError as e: print(f"HTTP {e.status_code}: {e.message}") print(f"Error code: {e.code}") print(f"Subcode: {e.subcode}") if e.is_transient: print("This error may be retryable") except ValidationError as e: print(f"Validation error: {e.message}") ```