# Python Microsoft Fabric API - Connection

The Dashboard fields, how tokens are obtained and refreshed, invoke for endpoints without a method of their own, and ping.

A Fabric connection is created once in the Dashboard and used in services as `self.microsoft.fabric[name]`. This page covers the connection form, how the connection uses the credentials, and the two methods that are not tied to one kind of item, `invoke` and `ping`.

## Dashboard fields {#dashboard-fields}

Under `Cloud → Microsoft Fabric`:

| Field | Value |
| --- | --- |
| Name | Any, used as `self.microsoft.fabric[name]` - the examples on these pages use `My Fabric` |
| Address | The Fabric API, `https://api.fabric.microsoft.com/v1` for the public cloud, or the address your admin gives you for a national cloud |
| Tenant ID | The directory (tenant) ID of the app registration, from its overview page in the Azure portal |
| Client ID | The application (client) ID, from the same page |
| Client secret | A secret created under the app registration's Certificates and secrets |

## What the app registration needs {#what-the-app-registration-needs}

An admin does three things once:

1. Enables the tenant setting "Service principals can use Fabric APIs" under `Tenant settings → Developer settings` in the Fabric admin portal
2. Adds the app registration to each workspace the connection should reach, as a Contributor for writing or a Viewer for reading only
3. Enables the Livy endpoint tenant setting on the same page, for `query` and the other Spark methods

## Tokens {#tokens}

The connection signs in with the client credentials grant - it posts the client ID and secret to `https://login.microsoftonline.com/<tenant ID>/oauth2/v2.0/token` and gets a token back. It gets two tokens, because the Fabric API and OneLake storage are separate services:

| Token | Scope | Used by |
| --- | --- | --- |
| API | `https://api.fabric.microsoft.com/.default` | Every method except the four `onelake_*` ones |
| Storage | `https://storage.azure.com/.default` | `onelake_list`, `onelake_read`, `onelake_write`, `onelake_delete`, and `write_table` while it uploads its files |

Each token is obtained the first time it is needed, kept, and replaced a minute before it would expire. When Fabric rejects a token anyway - for instance, the secret was rotated - the connection gets a new one and repeats the request once. Services never see a token.

## invoke {#invoke}

```python
conn.invoke(method, path, params=None, data=None)
```

Calls any endpoint of the Fabric API with the connection's token, for the parts of the API that have no method of their own.

| Parameter | Type | Meaning |
| --- | --- | --- |
| `method` | str | `GET`, `POST`, `PATCH`, `PUT` or `DELETE` |
| `path` | str | The path after the address, e.g. `/workspaces`, or a full URL Fabric handed back, such as a continuation URI |
| `params` | dict | Query string parameters, or none |
| `data` | dict | The JSON body, or none |

Returns the parsed JSON response, or nothing when the endpoint returned no body. A status code outside the success range raises an exception with the code and the response text.

```python
# -*- coding: utf-8 -*-

# Zato
from zato.server.service import Service

class Invoke(Service):

    def handle(self):

        workspace_id = '11111111-2222-3333-4444-555555555555'

        conn = self.microsoft.fabric['My Fabric']

        # Every item of one type in a workspace, through the API's own filter.
        path = f'/workspaces/{workspace_id}/items'
        params = {'type': 'Eventstream'}

        response = conn.invoke('GET', path, params=params)

        names = []
        for item in response['value']:
            names.append(item['displayName'])

        self.response.payload = {'eventstreams': names}
```

```json
{"eventstreams": ["events"]}
```

`conn.get(path, params)`, `conn.post(path, data, params)`, `conn.patch(path, data, params)` and `conn.delete(path, params)` are the same call with the method filled in. `conn.invoke_raw` takes the same parameters as `invoke` and returns the whole response object instead, for the headers.

## ping {#ping}

```python
conn.ping()
```

Confirms the connection works by obtaining a token and listing the workspaces the app registration can see. The Ping button in the Dashboard calls it, and a service can too. Returns nothing, raises an exception when the token or the listing fails, and logs how many workspaces it found.

```python
# -*- coding: utf-8 -*-

# Zato
from zato.server.service import Service

class Ping(Service):

    def handle(self):

        conn = self.microsoft.fabric['My Fabric']
        conn.ping()

        self.response.payload = {'connection': conn.name}
```

## See also {#see-also}

- [Your first Fabric integration](https://zato.io/docs/dev/examples/cloud/fabric/tutorial.html) - Creating the app registration and the connection step by step
- [Workspaces](https://zato.io/docs/dev/examples/cloud/fabric/api/workspaces.html) - What the connection can see once it is signed in
- [Events](https://zato.io/docs/dev/examples/cloud/fabric/api/events.html) - The connections that sign in as the same app registration for eventstreams

## Learn more {#learn-more}

- [Development documentation](https://zato.io/docs/dev/) - Everything about writing services, in one place
- [Requests and responses](https://zato.io/docs/dev/request-response/) - What a service receives, what it returns and how to shape both
- [Integration examples](https://zato.io/docs/dev/examples/) - Ready-made code for the systems you are likely to connect to
- [IDE and debugging](https://zato.io/docs/dev/ide/) - Write services in the Dashboard or in your own editor
- [Data models](https://zato.io/docs/dev/model/) - Declare inputs and outputs and have them validated for you
- [In-depth API tutorial](https://zato.io/tutorials/main/01.html) - The full platform tutorial, from installation to production patterns
