microsoft / vsmarketplace

Customer feedback and issue tracker repository for Visual Studio Marketplace
MIT License
40 stars 10 forks source link

Document marketplace API #238

Closed ssbarnea closed 1 year ago

ssbarnea commented 3 years ago

While marketplace API is public, there is no documentation about it, even partial. The old uservoice forum is now closed and finding the magic API requires extensive internet research on forums and digging the source code in order to reverse engineer the API calls to make.

Please document it, even if you start documenting only some of it.

Resources:

slashformotion commented 1 year ago

Any chance that will be done ?

prashantvc commented 1 year ago

The Marketplace Terms of Use do not allow use of APIs/services outside Visual Studio family of product. We do not have plan to change it.

If you are a Microsoft product team/FTE, please contact the Marketplace team for the API documentation.

jossef commented 1 year ago

Python code to assist in crawling VSCode extensions marketplace

also available in this gist: https://gist.github.com/jossef/8d7681ac0c7fd28e93147aa5044bc129

import requests
from requests.adapters import HTTPAdapter, Retry

def get_vscode_extensions(max_page=10000, page_size=100,
                          include_versions=True, include_files=True, include_category_and_tags=True, include_shared_accounts=True, include_version_properties=True,
                          exclude_non_validated=False, include_installation_targets=True, include_asset_uri=True, include_statistics=True,
                          include_latest_version_only=False, unpublished=False, include_name_conflict_info=True, api_version='7.2-preview.1', session=None):
    if not session:
        session = requests.session()

    headers = {'Accept': f'application/json; charset=utf-8; api-version={api_version}'}

    flags = 0
    if include_versions:
        flags |= 0x1

    if include_files:
        flags |= 0x2

    if include_category_and_tags:
        flags |= 0x4

    if include_shared_accounts:
        flags |= 0x8

    if include_shared_accounts:
        flags |= 0x8

    if include_version_properties:
        flags |= 0x10

    if exclude_non_validated:
        flags |= 0x20

    if include_installation_targets:
        flags |= 0x40

    if include_asset_uri:
        flags |= 0x80

    if include_statistics:
        flags |= 0x100

    if include_latest_version_only:
        flags |= 0x200

    if unpublished:
        flags |= 0x1000

    if include_name_conflict_info:
        flags |= 0x8000

    for page in range(1, max_page + 1):
        body = {
            "filters": [
                {
                    "criteria": [
                        {
                            "filterType": 8,
                            "value": "Microsoft.VisualStudio.Code"
                        }
                    ],
                    "pageNumber": page,
                    "pageSize": page_size,
                    "sortBy": 0,
                    "sortOrder": 0
                }
            ],
            "assetTypes": [],
            "flags": flags
        }

        r = session.post('https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery', json=body, headers=headers)
        r.raise_for_status()
        response = r.json()

        extensions = response['results'][0]['extensions']
        for extension in extensions:
            yield extension

        if len(extensions) != page_size:
            break

def main():
    retry_strategy = Retry(
        total=3,
        backoff_factor=1,
        status_forcelist=[429, 500, 502, 503, 504],
        allowed_methods=["HEAD", "GET", "OPTIONS"]
    )
    adapter = HTTPAdapter(max_retries=retry_strategy)
    session = requests.Session()
    session.mount("https://", adapter)
    session.mount("http://", adapter)

    for extension in get_vscode_extensions(session=session, page_size=10):
        extension_name = extension['extensionName']
        extension_description = extension['extensionName']
        extensions_versions = extension['versions']
        extensions_statistics = dict({(item['statisticName'], item['value']) for item in extension['statistics']})
        extension_publisher_username = extension['publisher']['publisherName']

        for extension_version_info in extensions_versions:
            extension_version = extension_version_info['version']
            extension_artifact_download_url = f'https://marketplace.visualstudio.com/_apis/public/gallery/publishers/{extension_publisher_username}/vsextensions/{extension_name}/{extension_version}/vspackage'
            print(extension_name, extension_description, extension_version, extension_artifact_download_url, extensions_statistics['install'])

if __name__ == '__main__':
    main()
StachuDotNet commented 9 months ago

https://stackoverflow.com/a/76559642/833921 for a more official path, I'm using vsce show <publisher>.<package> --json | jq '.versions[0].version for my use case, to get the "latest version"

Maybe vsce show will work for your needs too.

chrisbloom7 commented 2 months ago

Just in case anyone wants to experiment with this for the purposes of VS Code development, here's a way to get extended info about an extension from the api using a couple common command line utilities

json_data=$(cat <<- JSON
{
  "assetTypes": [],
  "filters": [
    {
      "criteria": [
        {
          "filterType": 7,
          "value": "<YOUR-EXTENSION-ID-HERE>"
        }
      ],
      "pageNumber": 1,
      "pageSize": 1
    }
  ],
  "flags": <YOUR-BITWISE-ORed-FLAGS-HERE>
}
JSON
)

# using wget
wget --accept="application/json;api-version=3.0-preview.1" --header="Accept: application/json;api-version=3.0-preview.1" --header="Content-Type: application/json" --post-data=$json_data -O- https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery | jq

# using httpie
echo $json_data | https --pretty=all https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery "Accept:application/json;api-version=3.0-preview.1" Content-Type:application/json

# using curl
curl -o- --header 'Accept: application/json;api-version=3.0-preview.1' --header 'Content-Type: application/json' --data $json_data https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery | jq

The flag value is used to customize the output from the API. A value of 16863 will return everything, or combine any number of flags using bitwise OR, i.e. if you only wanted includeLatestVersionOnly (512) along with includeCategoryAndTags (4) you'd use 516 for the flag.

DiskCrasher commented 1 month ago

The Marketplace Terms of Use do not allow use of APIs/services outside Visual Studio family of product. We do not have plan to change it.

Well that's rather shortsighted. Too bad for those of us who work in disconnected environments and need to acquire specific versions of .vsix files.