<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Fabric REST report/getDefinition Endpoint is not returning definition in Data Engineering</title>
    <link>https://community.fabric.microsoft.com/t5/Data-Engineering/Fabric-REST-report-getDefinition-Endpoint-is-not-returning/m-p/5187681#M16341</link>
    <description>&lt;P&gt;Hallo Fabric Community,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;DIV&gt;&lt;SPAN&gt;&lt;SPAN&gt;Fabric REST `&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;EM&gt;&lt;A href="https://api.fabric.microsoft.com/v1/workspaces/" target="_blank" rel="noopener"&gt;https://api.fabric.microsoft.com/v1/workspaces/&lt;/A&gt;{workspaceId}/reports/{reportId}&lt;/EM&gt;&lt;SPAN&gt;&lt;EM&gt;/getDefinition&lt;/EM&gt;`&lt;/SPAN&gt;&lt;SPAN&gt;&amp;nbsp;endpoint is not returning any definition. It is returning a json object like this `&lt;/SPAN&gt;&lt;PRE&gt;&lt;SPAN&gt;{'status': 'Succeeded',
 'createdTimeUtc': '2026-05-22T15:47:35.2651275',
 'lastUpdatedTimeUtc': '2026-05-22T15:47:35.4583119',
 'percentComplete': 100,
 'error': None}&lt;/SPAN&gt;&lt;/PRE&gt;&lt;SPAN&gt;&lt;SPAN&gt;`&lt;BR /&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&lt;SPAN&gt;&lt;SPAN&gt;I am looking to extract `&lt;SPAN class=""&gt;"path"&lt;/SPAN&gt;: &lt;SPAN class=""&gt;"report.json"`&lt;/SPAN&gt;&amp;nbsp;from the `definition` as showed in the official Documentation&lt;BR /&gt;&lt;BR /&gt;my code:&lt;BR /&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/DIV&gt;&lt;LI-CODE lang="python"&gt;def getReportDefinition(workspaceId: str, reportId: str, headers: dict) -&amp;gt; dict:
    """
    Fetch report definition, handling both 200 (sync) and 202 (async/polling).
    Returns the parsed definition dict.
    """
    _url = f"https://api.fabric.microsoft.com/v1/workspaces/{workspaceId}/reports/{reportId}/getDefinition"
    _response = requests.post(_url, headers=headers)

    # --- Synchronous response ---
    if _response.status_code == 200:
        return _response.json()

    # --- Asynchronous response: poll until complete ---
    if _response.status_code == 202:
        _operationUrl = _response.headers.get("Location")
        _retryAfter   = int(_response.headers.get("Retry-After", 10))

        if not _operationUrl:
            raise ValueError("202 received but no Location header found.")

        return _pollOperation(_operationUrl, _retryAfter, headers)

    _response.raise_for_status()


def _pollOperation(operationUrl: str, retryAfter: int, headers: dict) -&amp;gt; dict:
    """
    Poll a Fabric long-running operation until it succeeds or fails.
    Returns the final result payload.
    """
    MAX_POLL_ATTEMPTS = 20

    for _attempt in range(1, MAX_POLL_ATTEMPTS + 1):
        print(f"  Polling attempt {_attempt}/{MAX_POLL_ATTEMPTS} — waiting {retryAfter}s ...")
        time.sleep(retryAfter)

        _pollResponse = requests.get(operationUrl, headers=headers)
        _pollResponse.raise_for_status()

        _pollJson = _pollResponse.json()
        _status   = _pollJson.get("status", "").lower()

        if _status == "succeeded":
            # The completed result is either inline or needs a separate GET
            _resultUrl = _pollJson.get("createdTimeUtc") and _pollJson.get("percentComplete") and \
                         _pollJson.get("resourceLocation")
            
            if _resultUrl:
                # Some operations put the result at resourceLocation
                _resultResponse = requests.get(_resultUrl, headers=headers)
                _resultResponse.raise_for_status()
                return _resultResponse.json()
            
            # Result is embedded directly in the poll response
            return _pollJson

        if _status in ("failed", "cancelled"):
            _error = _pollJson.get("error", {})
            raise RuntimeError(
                f"Operation {_status}: [{_error.get('errorCode')}] {_error.get('message')}"
            )

        # Still running — respect a new Retry-After if provided
        retryAfter = int(_pollResponse.headers.get("Retry-After", retryAfter))

    raise TimeoutError(f"Operation did not complete after {MAX_POLL_ATTEMPTS} polling attempts.")


def decodeReportJson(definition: dict) -&amp;gt; dict:
    """
    Find report.json in definition parts, decode its InlineBase64 payload,
    and return the parsed JSON content.
    """
    _parts = definition.get("definition", {}).get("parts", [])

    for _part in _parts:
        if _part.get("path") == "report.json" and _part.get("payloadType") == "InlineBase64":
            _decoded = base64.b64decode(_part["payload"]).decode("utf-8")
            return json.loads(_decoded)

    raise ValueError("report.json not found in definition parts.")


# --- Main ---
WORKSPACE_ID = workspaceId
REPORT_ID    = reportId

_definition  = getReportDefinition(WORKSPACE_ID, REPORT_ID, CONTRIBUTOR_SP_HEADERS_FABRIC)&lt;/LI-CODE&gt;&lt;P&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;</description>
    <pubDate>Fri, 22 May 2026 16:11:03 GMT</pubDate>
    <dc:creator>Kuladeep</dc:creator>
    <dc:date>2026-05-22T16:11:03Z</dc:date>
    <item>
      <title>Fabric REST report/getDefinition Endpoint is not returning definition</title>
      <link>https://community.fabric.microsoft.com/t5/Data-Engineering/Fabric-REST-report-getDefinition-Endpoint-is-not-returning/m-p/5187681#M16341</link>
      <description>&lt;P&gt;Hallo Fabric Community,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;DIV&gt;&lt;SPAN&gt;&lt;SPAN&gt;Fabric REST `&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;EM&gt;&lt;A href="https://api.fabric.microsoft.com/v1/workspaces/" target="_blank" rel="noopener"&gt;https://api.fabric.microsoft.com/v1/workspaces/&lt;/A&gt;{workspaceId}/reports/{reportId}&lt;/EM&gt;&lt;SPAN&gt;&lt;EM&gt;/getDefinition&lt;/EM&gt;`&lt;/SPAN&gt;&lt;SPAN&gt;&amp;nbsp;endpoint is not returning any definition. It is returning a json object like this `&lt;/SPAN&gt;&lt;PRE&gt;&lt;SPAN&gt;{'status': 'Succeeded',
 'createdTimeUtc': '2026-05-22T15:47:35.2651275',
 'lastUpdatedTimeUtc': '2026-05-22T15:47:35.4583119',
 'percentComplete': 100,
 'error': None}&lt;/SPAN&gt;&lt;/PRE&gt;&lt;SPAN&gt;&lt;SPAN&gt;`&lt;BR /&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&lt;SPAN&gt;&lt;SPAN&gt;I am looking to extract `&lt;SPAN class=""&gt;"path"&lt;/SPAN&gt;: &lt;SPAN class=""&gt;"report.json"`&lt;/SPAN&gt;&amp;nbsp;from the `definition` as showed in the official Documentation&lt;BR /&gt;&lt;BR /&gt;my code:&lt;BR /&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/DIV&gt;&lt;LI-CODE lang="python"&gt;def getReportDefinition(workspaceId: str, reportId: str, headers: dict) -&amp;gt; dict:
    """
    Fetch report definition, handling both 200 (sync) and 202 (async/polling).
    Returns the parsed definition dict.
    """
    _url = f"https://api.fabric.microsoft.com/v1/workspaces/{workspaceId}/reports/{reportId}/getDefinition"
    _response = requests.post(_url, headers=headers)

    # --- Synchronous response ---
    if _response.status_code == 200:
        return _response.json()

    # --- Asynchronous response: poll until complete ---
    if _response.status_code == 202:
        _operationUrl = _response.headers.get("Location")
        _retryAfter   = int(_response.headers.get("Retry-After", 10))

        if not _operationUrl:
            raise ValueError("202 received but no Location header found.")

        return _pollOperation(_operationUrl, _retryAfter, headers)

    _response.raise_for_status()


def _pollOperation(operationUrl: str, retryAfter: int, headers: dict) -&amp;gt; dict:
    """
    Poll a Fabric long-running operation until it succeeds or fails.
    Returns the final result payload.
    """
    MAX_POLL_ATTEMPTS = 20

    for _attempt in range(1, MAX_POLL_ATTEMPTS + 1):
        print(f"  Polling attempt {_attempt}/{MAX_POLL_ATTEMPTS} — waiting {retryAfter}s ...")
        time.sleep(retryAfter)

        _pollResponse = requests.get(operationUrl, headers=headers)
        _pollResponse.raise_for_status()

        _pollJson = _pollResponse.json()
        _status   = _pollJson.get("status", "").lower()

        if _status == "succeeded":
            # The completed result is either inline or needs a separate GET
            _resultUrl = _pollJson.get("createdTimeUtc") and _pollJson.get("percentComplete") and \
                         _pollJson.get("resourceLocation")
            
            if _resultUrl:
                # Some operations put the result at resourceLocation
                _resultResponse = requests.get(_resultUrl, headers=headers)
                _resultResponse.raise_for_status()
                return _resultResponse.json()
            
            # Result is embedded directly in the poll response
            return _pollJson

        if _status in ("failed", "cancelled"):
            _error = _pollJson.get("error", {})
            raise RuntimeError(
                f"Operation {_status}: [{_error.get('errorCode')}] {_error.get('message')}"
            )

        # Still running — respect a new Retry-After if provided
        retryAfter = int(_pollResponse.headers.get("Retry-After", retryAfter))

    raise TimeoutError(f"Operation did not complete after {MAX_POLL_ATTEMPTS} polling attempts.")


def decodeReportJson(definition: dict) -&amp;gt; dict:
    """
    Find report.json in definition parts, decode its InlineBase64 payload,
    and return the parsed JSON content.
    """
    _parts = definition.get("definition", {}).get("parts", [])

    for _part in _parts:
        if _part.get("path") == "report.json" and _part.get("payloadType") == "InlineBase64":
            _decoded = base64.b64decode(_part["payload"]).decode("utf-8")
            return json.loads(_decoded)

    raise ValueError("report.json not found in definition parts.")


# --- Main ---
WORKSPACE_ID = workspaceId
REPORT_ID    = reportId

_definition  = getReportDefinition(WORKSPACE_ID, REPORT_ID, CONTRIBUTOR_SP_HEADERS_FABRIC)&lt;/LI-CODE&gt;&lt;P&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;</description>
      <pubDate>Fri, 22 May 2026 16:11:03 GMT</pubDate>
      <guid>https://community.fabric.microsoft.com/t5/Data-Engineering/Fabric-REST-report-getDefinition-Endpoint-is-not-returning/m-p/5187681#M16341</guid>
      <dc:creator>Kuladeep</dc:creator>
      <dc:date>2026-05-22T16:11:03Z</dc:date>
    </item>
    <item>
      <title>Re: Fabric REST report/getDefinition Endpoint is not returning definition</title>
      <link>https://community.fabric.microsoft.com/t5/Data-Engineering/Fabric-REST-report-getDefinition-Endpoint-is-not-returning/m-p/5187721#M16342</link>
      <description>&lt;P&gt;&lt;a href="https://community.fabric.microsoft.com/t5/user/viewprofilepage/user-id/1308737"&gt;@Kuladeep&lt;/a&gt;&amp;nbsp;getDefinition request is a Long Running Operation in Fabric REST API and it's a 3-step process:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;POST for getDefinition: it returns a 202 accepted with a link for the status poll in the location header.&lt;/LI&gt;&lt;LI&gt;&amp;nbsp;GET status: it returns 200 with the status - as you correctly showed in your post above. DOES NOT return the result yet, but the result link in the location.&lt;/LI&gt;&lt;LI&gt;GET result: a url for this in the status location header: returns the result in this format:&lt;BR /&gt;&lt;BR /&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;LI-CODE lang="javascript"&gt;{
  "definition": {
    "parts": [
      {
        "path": "report.json",
        "payload": "QmFzZTY0U3RyaW5n",
        "payloadType": "InlineBase64"
      },
      {
        "path": "definition.pbir",
        "payload": "QW5vdGhlckJhc2U2NFN0cmluZw",
        "payloadType": "InlineBase64"
      },
      {
        "path": ".platform",
        "payload": "ZG90UGxhdGZvcm1CYXNlNjRTdHJpbmc=",
        "payloadType": "InlineBase64"
      }
    ]
  }
}&lt;/LI-CODE&gt;&lt;P&gt;&lt;BR /&gt;In your code above you do not extract the result URL correctly from the status response location header. You should extrat the result URL from the location header of the status response when percentComplete == "100". Do it like this:&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;&lt;LI-CODE lang="markup"&gt; _resultUrl = _response.headers.get("Location")&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I tested in my environment and the process works correctly and returns the report definition in a form (obfuscated):&lt;/P&gt;&lt;LI-CODE lang="markup"&gt;{
  "definition": {
    "format": "PBIR-Legacy",
    "parts": [
      {
        "path": "definition.pbir",
        "payload": "ewogIC...",
        "payloadType": "InlineBase64"
      },
      {
        "path": "StaticResources/SharedResources/BaseThemes/CYxxxxxx.json",
        "payload": "ewogICJu...",
        "payloadType": "InlineBase64"
      },
      {
        "path": "report.json",
        "payload": "ewogICJjb25maW...",
        "payloadType": "InlineBase64"
      },
      {
        "path": ".platform",
        "payload": "ewo...",
        "payloadType": "InlineBase64"
      }
    ]
  }
}&lt;/LI-CODE&gt;&lt;P&gt;&lt;BR /&gt;Hope you find this helpful. In such case give it kudos and accept as a solution to help other community members.&lt;/P&gt;</description>
      <pubDate>Fri, 22 May 2026 17:34:17 GMT</pubDate>
      <guid>https://community.fabric.microsoft.com/t5/Data-Engineering/Fabric-REST-report-getDefinition-Endpoint-is-not-returning/m-p/5187721#M16342</guid>
      <dc:creator>apturlov</dc:creator>
      <dc:date>2026-05-22T17:34:17Z</dc:date>
    </item>
  </channel>
</rss>

