Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Don't miss out! 2025 Microsoft Fabric Community Conference, March 31 - April 2, Las Vegas, Nevada. Use code MSCUST for a $150 discount. Prices go up February 11th. Register now.

Reply
Shubhorin1
Frequent Visitor

Issue with 202 Status Code and Polling for Notebook Definition in Microsoft Fabric API

Hi Microsoft Fabric Team,

I am working on a project where I need to fetch the definition of a notebook from a workspace using the Microsoft Fabric API. While making the API call to the endpoint https://api.fabric.microsoft.com/v1/workspaces/{workspaceID}/notebooks/{notebookId}/getDefinition, I encounter a 202 Accepted response, which indicates that the request is still being processed.

I understand that this status code suggests that I need to poll a provided Location URL to check the status of the operation. However, I am facing some issues with this approach:

  1. After receiving the 202 Accepted response, I extract the Location URL from the response headers to begin polling the status of the notebook definition retrieval.

  2. I implemented a polling mechanism that rechecks the Location URL every few seconds until I receive a final result (200 OK).

  3. Despite following this approach, I receive a 403 Forbidden response with the following error message:

     
     

 

 

<TridentPublicApiErrorResponse> <errorCode>RequestFailed</errorCode> <message>Unable to process the request</message> <requestId>a06f0684-8978-425b-b8ff-6f114834efd2</requestId> </TridentPublicApiErrorResponse>

 

 

I've ensured that the access token used for authorization has the required scopes (e.g., Workspace.ReadWrite.All,Notebook.ReadWrite.All,Item.ReadWrite.All), and I am able to retrieve other resources using the same token. However, the polling mechanism for this particular case seems to fail with a 403 error.

My Questions:

  1. Is there any specific configuration or permission required for handling long-running operations (e.g., notebook definition retrieval) via the Microsoft Fabric API that I might be missing?
  2. Are there any best practices or additional headers I should include when polling the Location URL?
  3. Could there be a timeout or limitation on the number of times I can poll the status?
  4. I am doing all this in Microsoft Fabrics notebook so please give suggestions in python preferably 

Any insights into why I might be receiving the 403 Forbidden response during the polling process would be highly appreciated.

Thank you!

7 REPLIES 7
DaVinci-DB
New Member

Hi,

The code includes exponential backoff for polling and handles the 403 Forbidden response. Make sure to replace your_workspace_id, your_notebook_id, and your_access_token with your actual values.

 

import requests
import time

def get_notebook_definition(workspace_id, notebook_id, access_token):
    url = f"https://api.fabric.microsoft.com/v1/workspaces/{workspace_id}/notebooks/{notebook_id}/getDefinition"
    headers = {
        "Authorization": f"Bearer {access_token}"
    }
    
    response = requests.get(url, headers=headers)
    
    if response.status_code == 202:
        location_url = response.headers.get("Location")
        if not location_url:
            raise Exception("Location-Header nicht im 202-Response gefunden")
        
        # Polling mit exponentiellem Rückoff
        wartezeit = 1  # Beginne mit 1 Sekunde
        while True:
            poll_response = requests.get(location_url, headers=headers)
            if poll_response.status_code == 200:
                return poll_response.json()
            elif poll_response.status_code == 403:
                raise Exception("403 Forbidden: Anfrage konnte nicht verarbeitet werden")
            else:
                time.sleep(wartezeit)
                wartezeit = min(wartezeit * 2, 60)  # Begrenze die Wartezeit auf 60 Sekunden
    else:
        response.raise_for_status()

# Beispielaufruf
workspace_id = "deine_workspace_id"
notebook_id = "deine_notebook_id"
access_token = "dein_access_token"

try:
    notebook_definition = get_notebook_definition(workspace_id, notebook_id, access_token)
    print(notebook_definition)
except Exception as e:
    print(f"Fehler: {e}")

 

v-shex-msft
Community Support
Community Support

Hi @Shubhorin1,

For 403 error, it means your request is authenticated but isn’t authorized to perform the requested operation on the

given resource. If this issue only appear when you request with the specific location, it means the location not existed or your not has enough permission to processing them.

403 Forbidden vs 401 Unauthorized HTTP responses - Stack Overflow

For your code, it seems well, but I think you can increase the operations interval. (currently it seems send too quickly which may trigger the rest API request limits)

Regards,

Xiaoxin Sheng

Community Support Team _ Xiaoxin
If this post helps, please consider accept as solution to help other members find it more quickly.

Hi @v-shex-msft 
As an admin in my workspace, I have access to both the notebook from which I am making the API call and the target notebook whose content I am attempting to retrieve. Despite this, I am receiving a 403 (Forbidden) error. For the access token, I am currently using the following scopes: "https://api.fabric.microsoft.com/.default, Item.ReadWrite.All, Notebook.ReadWrite.All". With these scopes, I am able to successfully retrieve the list of notebooks within Fabric, but I am unable to access the content of the specified notebook. Is there an additional requirement or configuration needed to successfully call the API and access notebook content?

Hi @Shubhorin1,

As I said, the issue is caused by you not have permission to access. What the location that you requested?  
Notice:

I suppose some of folder and path you get currently not existed or release to users. So that you still not able to access and operate even if you have admin permission and configure the correct scope.

Regards,

Xiaoxin Sheng

Community Support Team _ Xiaoxin
If this post helps, please consider accept as solution to help other members find it more quickly.

Hello @v-shex-msft ,

Could you please guide me on where to configure access/permission for this? The notebook I am attempting to access is located within my workspace, and I am calling the API from the same workspace. Initially, I call the API to retrieve the list of all notebooks in my workspace, and then, using the notebook ID obtained from the results, I attempt to fetch the content of a specific notebook.

v-shex-msft
Community Support
Community Support

HI @Shubhorin1,

Can you please share some more detail about these processes? I think 403 error may means the credentials is invalid or expired during these loop operations to REST API.
For this scenario, perhaps you can add refresh token operations and reduce the frequency during sending these requests.

In addition, you can also try to use thread functions in notebook to achieve async operations:

python - Calling pyspark function asynchronously with concurrent.futures - Stack Overflow

Regards,

Xiaoxin Sheng

Community Support Team _ Xiaoxin
If this post helps, please consider accept as solution to help other members find it more quickly.

Hi @v-shex-msft 
Initially, I generate an access token using the Client ID, Client Secret, and Tenant ID, while specifying the necessary scopes (Workspace.ReadWrite.All, Item.ReadWrite.All). With the freshly obtained token, I proceed to call the Get Definition API using the Workspace ID and Notebook ID.

Upon invoking the API, I receive a 202 Accepted status code, indicating the request is being processed. To handle this, I implemented a polling mechanism that repeatedly checks the Location URL provided in the response header. This polling system ensures I can track the progress of the request asynchronously.

However, when navigating to the Location URL, I encounter a 403 Forbidden error. To address this, I have also incorporated an async/await system to fetch the link and concurrently retrieve the latest status in real-time.
so below i am attaching 2 approaches i used to tackle this situation can you please give your insights on this 
1) without asynch await 

 

 

import requests
import time
import json

workspaceID = ''  
notebookId = '' 
api_url = f'https://api.fabric.microsoft.com/v1/workspaces/{workspaceID}/notebooks/{notebookId}/getDefinition'

access_token = ''  

headers = {
    "Authorization": f"Bearer {access_token}",  
    "Content-Type": "application/json"
}

response = requests.post(api_url, headers=headers)

if response.status_code == 200:
    notebooks = response.json()  
    print("Response from the API:")
    print(json.dumps(notebooks, indent=4))

elif response.status_code == 202:
    print("Request accepted. Processing is not yet complete.")
    
    location_url = response.headers.get('Location')
    if location_url:
        print(f"Check the status at: {location_url}")
        
        while True:
            time.sleep(5)  
            
            status_response = requests.get(location_url, headers=headers)
            if status_response.status_code == 200:
                result = status_response.json()
                print("Final result:")
                print(json.dumps(result, indent=4))
                break
            elif status_response.status_code == 202:
                print("Still processing...")
            else:
                print(f"Error checking status: {status_response.status_code}, {status_response.text}")
                break
            
    else:
        print("No location URL provided for status checking.")
else:
    print(f"Failed to fetch notebooks: {response.status_code}, {response.text}")

 

 

2) With Async await 

 

 

import aiohttp
import asyncio
import json
import nest_asyncio

nest_asyncio.apply()

workspaceID = ''  
notebookId = '' 
api_url = f'https://api.fabric.microsoft.com/v1/workspaces/{workspaceID}/notebooks/{notebookId}/getDefinition'

access_token = ''  
async def fetch_notebook(session):
    headers = {
        "Authorization": f"Bearer {access_token}",
        "Content-Type": "application/json"
    }

    async with session.post(api_url, headers=headers) as response:
        if response.status == 200:
            notebooks = await response.json()
            print("Response from the API:")
            print(json.dumps(notebooks, indent=4))
        elif response.status == 202:
            print("Request accepted. Processing is not yet complete.")
            location_url = response.headers.get('Location')
            if location_url:
                await poll_status(session, location_url)
            else:
                print("No location URL provided for status checking.")
        else:
            print(f"Failed to fetch notebooks: {response.status}, {await response.text()}")

async def poll_status(session, location_url):
    while True:
        async with session.get(location_url) as status_response:
            if status_response.status == 200:
                final_result = await status_response.json()
                print("Final result:")
                print(json.dumps(final_result, indent=4))
                break
            elif status_response.status == 202:
                print("Still processing...")
                await asyncio.sleep(5)  
            else:
                print(f"Error checking status: {status_response.status}, {await status_response.text()}")
                break

async def main():
    async with aiohttp.ClientSession() as session:
        await fetch_notebook(session)

await main()

 

 

Please let me know if there are any changes to be made in the code 
Thanks!!

 

Helpful resources

Announcements
Las Vegas 2025

Join us at the Microsoft Fabric Community Conference

March 31 - April 2, 2025, in Las Vegas, Nevada. Use code MSCUST for a $150 discount!

ArunFabCon

Microsoft Fabric Community Conference 2025

Arun Ulag shares exciting details about the Microsoft Fabric Conference 2025, which will be held in Las Vegas, NV.

December 2024

A Year in Review - December 2024

Find out what content was popular in the Fabric community during 2024.

Top Solution Authors
Top Kudoed Authors