Sunday, May 27, 2018

Can't we just do a "Hello, world"?

The Joomla! component tutorial walks you through creating a Model-View-Controller (MVC) component. However, the Absolute basics of a component page also mentions that a component doesn't have to be MVC; it claims that a flat model is supported, but then spends no time explaining how it's supposed to work.

Quite simply, actually. A component has a startup file with the name that matches the component's element without the initial com_ (e. g. the startup file for com_foobar would be foobar.php). Joomla executes that file, intercepts whatever output it generates, and inserts that output into the content area of the HTML document, surrounded by the template and the modules.

Joomla knows which component to invoke by checking the option parameter in the query string. So navigating to index.php?option=com_foobar would execute our component. I haven't figured out yet if/how one can expose a flat model component via SEO friendly URLs. I haven't figured out, either, if/how components like this can register their menu item types. MVC ones can, that's covered in the tutorial.

Joomla uses output buffering to capture the output of the component, so none of the document's initial HTML is emitted before the component is done working. This way, a component can also manipulate HTTP headers, including redirection - something it won't be able to do, were Joomla to render the document in order. If the component doesn't want the rest of the document around its output, it's free to call exit in the end. That will flush the output buffer to the wire instead of letting Joomla capture and handle it.

A flat component like this only needs an XML manifest, the startup file under the "site" subfolder, and index.html under site to comply with the Joomla convention.

Friday, May 25, 2018

Name means ID, ID means name

Let's take a break from TFS.

This time, it's Joomla!, a popular Web CMS, which has an expansive, if sorely underdocumented, extension interface. Once again, I've discovered a little undocumented something, and would like to share.

Joomla has several types of extensions - plugins, modules, components, templates. I was fooling around with components, and discovered a rather unpleasant shortcoming. Components have a manifest with a <name> element in it. By default, the value of the name serves as both the the element (the internal name), for URLs and such, and as the display name. So, if you have a component that you want listed as "Widget Frobulator by Acme Software", Joomla will internally call it com_widgetfrobulatorbyacmesoftware. Meanwhile, I'd rather call mine com_frob.

Undocumented parameters to the rescue. In the component manifest, under <extension>, there can be an element called <element>. If it's present, its value explicitly provides the internal name. It may or may not be prefixed with com_; if it's not, Joomla will add that. So my component is known to Joomla as com_frob, and life is good again.

When it comes to locating the component's main script, Joomla goes by element and not by name, removing the initial com_ from it. So, in our example, the startup file of the component would have to be frob.php.

The built-in components of Joomla use a different technique to make sure the display name doesn't match the element. They don't have an <element> in their manifests, their <name> is the element (e. g. com_content for the Articles component), and the language file includes a translation from com_content to Articles. My component didn't have any translations.

With plugins, the logic for assigning the element is different. Unless <element> is there, Joomla goes over the <files>, takes the first <filename> with the attribute "plugin", and uses the value of that attribute as the element. So, if the <files> portion of the manifest goes:

<files>
    <filename>index.html</filename>
    <filename plugin="foo">foo.php</plugin>
</files>


Then "foo" will be the plugin's internal name. There's little point in providing <element> explicitly.

Haven't tried it with modules or templates.

This holds as of Joomla 3.8.8.

Monday, May 21, 2018

Constrained and dignified

Another day, another TFS discovery.

I was facing a minor usability issue. We have an extension with several custom menu commands for release definitions. Out of those, two only make sense for server administrators. For anybody else, they'd error out anyway. The menu was getting crowded, so I wanted to see if I could make the admin-only commands hidden for non-admin users.

In TFS extension lingo, the custom menu commands are contributions. They're described by a JSON manifest. On the surface, there's nothing in the manifest docs about conditionally visible contributions. However, a careful look at the JavaScript API docs reveals something interesting - the Contribution object, as returned from VSS.getContribution(), has a property called "constraints", and it's an array of ContributionConstraint objects.

Looking at the sources of the TFX tool reveals that "constraints" is a valid JSON element in the extension manifest, and it's expected to be an array.

Now we're getting somewhere. So, what goes into that array? One would guess, objects that correspond to the ContributionConstraint class, one with the following properties:
  • name
  • properties
  • group
  • inverse
According to the docs, the "name" property contains "name of the IContributionFilter class". IContributionFilter is not a JavaScript object. However, it is a C# interface. Poking around TFS assemblies with ILSpy reveals it in Microsoft.VisualStudio.Services.ExtensionManagement.Sdk.Server.dll, and there's a bunch of derived classes in bin\Plugins\Microsoft.VisualStudio.Services.ExtensionManagement.Sdk.Plugins.dll. Incidentally, the IContributionFilter interface has a Name property. One would presume it corresponds to the "name" property of the "constraint" JavaScript object and the manifest line.

Each of those filter classes has a name and supports a set of parameters:
  • Security (class SecurityFilter)
    • namespaceId (GUID)
    • namespaceToken (string)
    • permission (int)
    • allowSystemContext (optional bool)
    • serviceInstanceType (optional GUID)
  • ExtensionActive (class ActiveExtensionFilter)
    • extensionId (string)
  • ExtensionLicensed (class ExtensionLicensedFilter)
    • extensionId (string)
    • extension-rights (object with a set of bool-valued properties)
  • Feature (class FeatureFilter)
    • featureId (string)
  • FeatureFlag (class FeatureFlagFilter)
    • featureName (string)
  • FeatureEnabled (class LegacyFeatureEnabledFilter)
    • featureName (string)

I've worked with Security, since it directly relates to my issue. The "namespaceId" property corresponds to the GUID of the security namespace (see the contents of Tfs_Configuration.dbo.tbl_SecurityNamespace for the list of those). The "namespaceToken" property corresponds to the token of a securable object. There are many classes of those in TFS, and the rules for generating tokens are different - poke around tbl_SecurityAccessControlEntry to see. The "permission" property contains a bit mask to check - to see the bit values of rights, see the contents of  Tfs_Configuration.dbo.tbl_SecurityAction. The structure of TFS access control lists is a discussion for another day.

So the Security constraint would check if the current user has the specified rights on the specified securable object, and if not, the contribution will not be displayed. Bingo! All I had to do was find a server-level securable object that only admins could manage. A certain restricted app pool did the trick.

The system of constraints is not documented and is barely acknowledged. However, TFS makes some use of it internally - the various built-in hubs are treated like contributions and some of them have constraints.

One can designate a constraint for a custom extension, too. In the manifest, under the contribution object, a constraint could look like this:

{
  "id": "mycommand",
  "type": "ms.vss-web.action",
  "constraints": [
  {
    "name": "Security",
    "properties": {
        "namespaceId":"101EAE8C-1709-47F9-B228-0E476C35B3BA",                "namespaceToken":"AgentPools/17/",
        "permission": 27 }
  }],
  // More contribution stuff...
}

Monday, April 30, 2018

All TFS clients

The TFS API continues to be sorely underdocumented. This time, let's talk about the .NET one for a change. You're supposed to first construct a VssConnection, then get a client class or several. There's a separate client for source control, a client for work items, one for build/release tasks, etc. Here are all client classes that I could find in TFS 2018u1:

In the Microsoft.TeamFoundation namespace:
  • WorkItemTracking.Client.WitRestClient
  • WorkItemTracking.WebApi.WorkItemTrackingHttpClient
  • Build.WebApi.XamlBuildHttpClient
  • Build.WebApi.BuildHttpClient
  • Chat.WebApi.ChatHttpClient
  • Core.WebApi.TeamHttpClient
  • Core.WebApi.ProcessHttpClient
  • Core.WebApi.TemporaryDataHttpClient
  • Core.WebApi.IdentityMruHttpClient
  • Core.WebApi.ProjectCollectionHttpClient
  • Core.WebApi.ConnectedServiceHttpClient
  • Core.WebApi.ProxyHttpClient
  • Core.WebApi.ProjectHttpClient
  • Core.WebApi.TaggingHttpClient
  • DistributedTask.WebApi.TaskAgentHttpClient
  • DistributedTask.WebApi.Legacy.LegacyTaskAgentPackageHttpClient
  • DistributedTask.WebApi.TaskHttpClient
  • Policy.WebApi.PolicyHttpClient
  • SourceControl.WebApi.TfvcHttpClient
  • SourceControl.WebApi.GitHttpClient
  • Test.WebApi.TestHttpClient
  • TestManagement.WebApi.TestHttpClient
  • Work.WebApi.WorkHttpClient
  • WorkItemTracking.Client.WitRestClient (nonpublic)
In the Microsoft.VisualStudio.Services namespace:
  • CodeReview.Discussion.WebApi.DiscussionHttpClient
  • CodeReview.WebApi.CodeReviewHttpClient
  • DevTestLabs.Client.EnvironmentClientV2
  • DevTestLabs.Client.EnvironmentDefinitionClientV2
  • DevTestLabs.Client.EnvironmentOperationClient
  • DevTestLabs.Client.IpAddressClient
  • DevTestLabs.Client.ProviderClient
  • DevTestLabs.Client.ProviderDataClient
  • ReleaseManagement.WebApi.Clients.RMHttpClient
  • ReleaseManagement.WebApi.Clients.ReleaseHttpClient2
  • CustomerIntelligence.WebApi.CustomerIntelligenceHttpClient
  • Zeus.BlobCopyRequestHttpClient
  • Zeus.DatabaseMigrationHttpClient
  • TokenSigningKeyLifecycle.Client.TokenSigningKeyHttpClient
  • Security.Client.SecurityBackingStoreHttpClient
  • Security.Client.SecurityHttpClient
  • Notification.Client.PersistedNotificationHttpClient
  • Location.Client.LocationHttpClient
  • Identity.Client.IdentityHttpClient
  • Identity.Client.PropertyCacheHttpClient
  • Identity.Mru.Client.IdentityMruHttpClient
  • FileContainer.Client.FileContainerHttpClient
  • FeatureAvailability.WebApi.FeatureAvailabilityHttpClient
  • Directories.DirectoryService.Client.DirectoryHttpClient
  • Commerce.Client.BillingHttpClient
  • Commerce.Client.CommercePackageHttpClient
  • Commerce.Client.ConnectedServerHttpClient
  • Commerce.Client.MeteringHttpClient
  • Commerce.Client.OfferMeterPriceHttpClient
  • Commerce.Client.CommerceOfferMeterHttpClient
  • Commerce.Client.SubscriptionHttpClient
  • ClientNotification.Client.ClientNotificationHttpClient
  • Account.Client.AccountHttpClient
  • OAuth.Client.OAuthHttpClient
  • Operations.OperationsHttpClient
  • UserMapping.Client.UserMappingHttpClient
  • Profile.Client.ProfileHttpClient
  • Organization.Client.OrganizationHttpClient
  • Organization.Client.OrganizationPolicyHttpClient
  • DelegatedAuthorization.Client.DelegatedAuthorizationHttpClient
  • Compliance.Client.ComplianceHttpClient
  • Settings.WebApi.SettingsHttpClient
  • Servicing.Client.ServiceLevelHttpClient
  • Licensing.Client.ExtensionLicensingHttpClient
  • Licensing.Client.LicensingHttpClient
  • WebApi.HttpClients.TokenHttpClient

Friday, April 27, 2018

Who am I and what are my rights (in TFS)?

Some time ago, we've discussed OAuth in TFS. Recently, I've been attacking a related problem - we have a valid OAuth-based connection (a VssConnection object), it can invoke some REST endpoints via OAuth, but which ones? Turns out, the allowed scopes are stored within an OAuth token, it just takes a bit of parsing to retrieve. The following line on an ASPX page returns the scopes for a token:

string Scopes = new System.IdentityModel.Tokens.JwtSecurityToken(Token).Payload["scp"];

There's a sample gist for that.



This came up as I was solving a bigger problem - what exactly is the security context that custom build/release tasks get? When you have a custom Powershell task (or a script in the built-in Powershell task), it gets a global variable called distributedTaskContext. I don't think it's documented anywhere, but you can find references to it in Microsoft's own examples.

Anyway, one can use that variable to call TFS back. You can instantiate .NET client objects and invoke all kinds of API - release, source control, you name it. But the security context is clearly not that of the current service account. Looking at the HTTP traffic, one can see that the HTTP requests back to TFS go with an Authorization: Bearer header with a token. The token, it turns out, can be easily retrieved from the distributedTaskContext:

$Token = $distributedTaskContext.GetEndpoint("SystemVssConnection").Authorization.Parameters.AccessToken

But what is the identity behind the token? Turns out, there's a REST endpoint for that, and invoking it with the token gives you the current user:

$wc = New-Object System.Net.WebClient
$wc.Headers["Authorization"] = "Bearer " + $Token
$wc.DownloadString("http://tfs.acme.com:8080/tfs/_api/_common/GetUserProfile?__v=5")

Still, an OAuth client has two parts to its security context: the user, and the scope(s). For the scopes, there's no built-in endpoint that I could find, so I put together my own.

For the record, the user behind the token is an artificial one. The identity record goes:

"IdentityType": "user",
"FriendlyDisplayName": "Project Collection Build Service (TEAM FOUNDATION)",
"DisplayName": "Project Collection Build Service (TEAM FOUNDATION)",
"SubHeader": "Build\\233e4ccc-d129-4ba4-9c5b-ea82c7ae1d15",
"TeamFoundationId": "7a3195ee-870e-4151-ba58-1e522732086c",
"EntityId": "vss.ds.v1.ims.user.7a3195ee870e4151ba581e522732086c",
"Errors": [],
"Warnings": [],
"Domain": "Build",
"AccountName": "233e4ccc-d129-4ba4-9c5b-ea82c7ae1d15",
"IsWindowsUser": false,
"MailAddress": ""

There's one user like this in every team collection. It belongs to a server-level group called "Security Service Group", and also to a collection level group with the same name. The security editing window of TFS, however, has no problem locating this user.

The scope on the token is "app_token". That is a valid scope, and it allows access to all endpoints and all methods in TFS.


This, in turn, came up as I was solving an even bigger problem - how does one make the behavior of a custom Powershell release task conditional upon the identity of the current agent pool? My answer was - custom capabilities. In order to retrieve the capabilities, I needed to know who should I grant the read access on the pool to, and whether the custom task is allowed to call the pool-related REST endpoints.

Friday, March 16, 2018

All OAuth scopes in TFS 2018.1

Some time ago, I've discussed dumping all OAuth scopes in TFS, both documented and undocumented.

Now I have a TFS 2018 update 1 instance, and here's the OAuth scope dump for that version. Notable addition: wiki.

The same caveat applies: some of those endpoints might be VSTS-only.

  preview_api_all
  • /_apis#OPTIONS
  • /DefaultCollection/_apis#OPTIONS
  • /_apis/connectiondata#GET
  • /DefaultCollection/_apis/connectiondata#GET
  • /_apis/ServiceDefinitions#GET
  • /_apis/build/builds#GET+PATCH+DELETE
  • /_apis/build/qualities#GET+PUT+DELETE
  • /_apis/build/requests#GET+POST+PATCH+DELETE
  • /_apis/build/definitions
  • /_apis/build/queues
  • /DefaultCollection/_apis/build/builds#GET+PATCH+DELETE
  • /DefaultCollection/_apis/build/qualities#GET+PUT+DELETE
  • /DefaultCollection/_apis/build/requests#GET+POST+PATCH+DELETE
  • /DefaultCollection/_apis/build/definitions
  • /DefaultCollection/_apis/build/queues
  • /DefaultCollection/_apis/resources/Containers#GET
  • /DefaultCollection/*/_apis/build/builds#GET+PATCH+DELETE+PUT+POST
  • /DefaultCollection/*/_apis/build/definitions#GET+POST+PUT+DELETE
  • /DefaultCollection/*/_apis/build/requests#GET+POST+PATCH+DELETE
  • /DefaultCollection/*/_apis/build/qualities#GET+PUT+DELETE
  • /DefaultCollection/*/_apis/build/tags#GET
  • /DefaultCollection/*/_apis/build/options#GET
  • /DefaultCollection/_apis/build/queues#GET
  • /DefaultCollection/_apis/build/options#GET
  • /DefaultCollection/_apis/build/controllers#GET
  • /_apis/accounts
  • /_apis/profile/profiles
  • /_apis/projectCollections
  • /_apis/tagging#GET+POST+PATCH+DELETE
  • /DefaultCollection/_apis/projects#GET+POST+PATCH+DELETE
  • /DefaultCollection/_apis/tagging#GET+POST+PATCH+DELETE
  • /_apis/notifications/*/eventdefinitions
  • /_apis/hooks/consumers
  • /_apis/hooks/publishers
  • /_apis/hooks/subscriptions#GET+POST+PUT+DELETE
  • /_apis/hooks/inputValuesQuery#POST
  • /_apis/hooks/notificationsQuery#POST
  • /_apis/hooks/subscriptionsQuery#POST
  • /_apis/hooks/publishersQuery#POST
  • /DefaultCollection/_apis/hooks/consumers
  • /DefaultCollection/_apis/hooks/publishers
  • /DefaultCollection/_apis/hooks/subscriptions#GET+POST+PUT+DELETE
  • /DefaultCollection/_apis/hooks/inputValuesQuery#POST
  • /DefaultCollection/_apis/hooks/notificationsQuery#POST
  • /DefaultCollection/_apis/hooks/subscriptionsQuery#POST
  • /DefaultCollection/_apis/hooks/publishersQuery#POST
  • /_apis/chat/rooms/*/messages#GET+POST+PUT+PATCH+DELETE
  • /_apis/chat/rooms#GET+POST+PUT+PATCH+DELETE
  • /DefaultCollection/_apis/chat/rooms/*/messages#GET+POST+PUT+PATCH+DELETE
  • /DefaultCollection/_apis/chat/rooms#GET+POST+PUT+PATCH+DELETE
  • /_apis/tfvc/branches
  • /_apis/tfvc/changesets
  • /_apis/tfvc/labels
  • /_apis/tfvc/shelvesets
  • /_apis/tfvc/workspaces#GET+POST
  • /_apis/tfvc/changesetsBatch#POST
  • /_apis/tfvc/itemBatch#POST
  • /DefaultCollection/_apis/tfvc/branches
  • /DefaultCollection/_apis/tfvc/changesets
  • /DefaultCollection/_apis/tfvc/items
  • /DefaultCollection/_apis/tfvc/labels
  • /DefaultCollection/_apis/tfvc/shelvesets
  • /DefaultCollection/_apis/tfvc/workspaces#GET+POST
  • /DefaultCollection/_apis/tfvc/changesetsBatch#POST
  • /DefaultCollection/_apis/tfvc/itemBatch#POST
  • /DefaultCollection/*/_apis/tfvc#GET+POST
  • /_apis/git/repositories#GET+POST
  • /_apis/git/repositories/*/commits
  • /_apis/git/*/repositories/*/commits
  • /_apis/git/repositories/*/commits/*/statuses#GET+POST
  • /_apis/git/*/repositories/*/commits/*/statuses#GET+POST
  • /_apis/git/repositories/*/forks/*#GET
  • /_apis/git/*/repositories/*/forks/*#GET
  • /_apis/git/repositories/*/forkSyncRequests#GET+POST
  • /_apis/git/repositories/*/forkSyncRequests/*#GET
  • /_apis/git/*/repositories/*/forkSyncRequests#GET+POST
  • /_apis/git/*/repositories/*/forkSyncRequests/*#GET
  • /_apis/git/repositories/*/pushes#GET+POST
  • /_apis/git/*/repositories/*/pushes#GET+POST
  • /_apis/git/repositories/*/pushes/*
  • /_apis/git/*/repositories/*/pushes/*
  • /_apis/git/repositories/*#GET+PATCH+DELETE
  • /_apis/git/*/repositories/*#GET+PATCH+DELETE
  • /_apis/git/*/repositories#GET+POST
  • /DefaultCollection/_apis/git/repositories#GET+POST
  • /DefaultCollection/_apis/git/repositories/*/commits
  • /DefaultCollection/_apis/git/*/repositories/*/commits
  • /DefaultCollection/_apis/git/repositories/*/commits/*/statuses#GET+POST
  • /DefaultCollection/_apis/git/*/repositories/*/commits/*/statuses#GET+POST
  • /DefaultCollection/_apis/git/repositories/*/forks/*#GET
  • /DefaultCollection/_apis/git/*/repositories/*/forks/*#GET
  • /DefaultCollection/_apis/git/repositories/*/forkSyncRequests#GET+POST
  • /DefaultCollection/_apis/git/repositories/*/forkSyncRequests/*#GET
  • /DefaultCollection/_apis/git/*/repositories/*/forkSyncRequests#GET+POST
  • /DefaultCollection/_apis/git/*/repositories/*/forkSyncRequests/*#GET
  • /DefaultCollection/_apis/git/repositories/*/pushes#GET+POST
  • /DefaultCollection/_apis/git/*/repositories/*/pushes#GET+POST
  • /DefaultCollection/_apis/git/repositories/*/pushes/*
  • /DefaultCollection/_apis/git/*/repositories/*/pushes/*
  • /DefaultCollection/_apis/git/repositories/*#GET+PATCH+DELETE+POST
  • /DefaultCollection/_apis/git/*/repositories/*#GET+PATCH+DELETE+POST
  • /DefaultCollection/_apis/git/*/repositories#GET+POST
  • /DefaultCollection/_apis/git/repositories/*/pullrequests#GET+POST+PUT+PATCH+DELETE
  • /DefaultCollection/_apis/git/*/repositories/*/pullrequests#GET+POST+PUT+PATCH+DELETE
  • /DefaultCollection/*/_apis/git/repositories#GET+POST+PUT+PATCH+DELETE
  • /DefaultCollection/_apis/codereview/reviews#GET
  • /DefaultCollection/*/_apis/codereview/reviews#GET+POST+PUT+PATCH+DELETE
  • /DefaultCollection/*/_apis/codereview/reviewsbatch#POST
  • /DefaultCollection/*/_apis/codereview/settings#GET+POST+PUT
  • /DefaultCollection/_apis/visits/artifactVisits#PUT
  • /DefaultCollection/_apis/visits/artifactVisitsBatch#POST
  • /DefaultCollection/_apis/visits/artifactStatsBatch#POST
  • /DefaultCollection/*/_apis/policy/Evaluations#GET+PATCH
  • /_apis/wit/attachments#GET+POST
  • /_apis/wit/queries#GET+POST+PATCH+DELETE
  • /DefaultCollection/_apis/wit/attachments#GET+POST
  • /DefaultCollection/_apis/wit/queries#GET+POST+PATCH+DELETE
  • /DefaultCollection/*/*/_apis/wit/queries#GET+POST+PATCH+DELETE
  • /_apis/wit/fields#GET
  • /_apis/wit/wiql#GET+POST
  • /_apis/wit/workitemrelationtypes#GET
  • /_apis/wit/workitems#GET+POST+PATCH
  • /_apis/wit/workitemtypecategories#GET
  • /_apis/wit/workitemtypes#GET
  • /_apis/wit/$ruleEngine#POST
  • /_apis/wit/$batch#POST
  • /_apis/wit/artifactlinktypes#GET
  • /_apis/wit/artifacturiquery#POST
  • /DefaultCollection/_apis/wit/artifactlinktypes#GET
  • /DefaultCollection/_apis/wit/artifacturiquery#POST
  • /DefaultCollection/_apis/wit/fields#GET
  • /DefaultCollection/_apis/wit/wiql#GET+POST
  • /DefaultCollection/_apis/wit/workitemrelationtypes#GET
  • /DefaultCollection/_apis/wit/workitems#GET+POST+PATCH+DELETE
  • /DefaultCollection/_apis/wit/$ruleEngine#POST
  • /DefaultCollection/_apis/wit/$batch#POST
  • /DefaultCollection/_apis/wit/workitemtypetemplate#GET+POST
  • /DefaultCollection/*/_apis/wit/fields#GET
  • /DefaultCollection/*/_apis/wit/classificationnodes#GET+POST+PATCH+DELETE
  • /DefaultCollection/*/_apis/wit/queries#GET+POST+PATCH+DELETE
  • /DefaultCollection/*/_apis/wit/wiql#GET+POST
  • /DefaultCollection/*/_apis/wit/workitems#GET+PATCH+DELETE
  • /DefaultCollection/*/_apis/wit/workitems#GET+POST+PATCH+DELETE
  • /DefaultCollection/*/_apis/wit/workitemtypecategories#GET
  • /DefaultCollection/*/_apis/wit/workitemtypes#GET
  • /DefaultCollection/*/_apis/wit/workitemtypetemplate#GET+POST
  • /DefaultCollection/*/*/_apis/wit/templates#GET+PUT+POST+DELETE
  • /DefaultCollection/*/*/_apis/wit/queries#GET+POST+PATCH+DELETE
  • /DefaultCollection/*/*/_apis/wit/wiql#GET+POST
  • /DefaultCollection/_apis/resources/Containers/*
  • /_apis/resources/Containers/*
  • /_api/_wit/teamProjects
  • /DefaultCollection/_api/_wit/teamProjects
  • /DefaultCollection/*/_apis/work/boards#GET+PUT+PATCH
  • /DefaultCollection/*/*/_apis/work/boards#GET+PUT+PATCH
  • /DefaultCollection/*/_apis/work/teamsettings#GET+POST+PATCH+DELETE
  • /DefaultCollection/*/*/_apis/work/teamsettings#GET+POST+PATCH+DELETE+PUT
  • /DefaultCollection/*/_apis/work/processconfiguration#GET
  • /DefaultCollection/*/_apis/work/backlogconfiguration#GET
  • /DefaultCollection/*/*/_apis/work/backlogconfiguration#GET
  • /_apis/clt/testdrops#GET+POST
  • /_apis/clt/testruns#GET+POST+PATCH
  • /_apis/clt/testruns/*/errors
  • /_apis/clt/testruns/*/messages
  • /_apis/clt/testruns/*/results
  • /_apis/clt/testruns/*/counterinstances
  • /_apis/clt/testruns/*/countersamples
  • /_apis/clt/apm
  • /_apis/clt/configuration
  • /_apis/clt/agentgroups#GET+POST+PATCH+DELETE
  • /_apis/clt/agentgroups/*/agents#GET+POST+PATCH+DELETE
  • /DefaultCollection/*/_apis/test#GET+POST+PATCH+DELETE
  • /_apis/test/suites
  • /_apis/Identities#GET+PUT+DELETE
  • /_apis/IdentityBatch#POST
  • /_apis/Groups#GET+DELETE+POST
  • /_apis/Scopes#GET+PUT+PATCH+DELETE
  • /DefaultCollection/_apis/discussion/threads#GET+POST+PATCH+DELETE
  • /DefaultCollection/_apis/discussion/threadsBatch#POST
  • /DefaultCollection/_apis/discussion/comments#PATCH
  • /_apis/Commerce/*#GET
  • /_apis/Commerce/Subscription/*/*#GET+PUT
  • /_apis/gallery/*#GET
  • /_apis/gallery/acquisitionrequests/*#POST
vso.base
  • /_apis#OPTIONS
  • /DefaultCollection/_apis#OPTIONS
  • /_apis/connectiondata#GET
  • /DefaultCollection/_apis/connectiondata#GET
  • /_apis/ServiceDefinitions#GET
  • /_apis/resourceareas#GET
  • /DefaultCollection/_apis/resourceareas#GET
  • /_apis/operations#GET
  • /DefaultCollection/_apis/operations#GET
  • /_apis/permissions#GET
  • /_apis/SecurityNamespaces#GET
  • /_apis/AccessControlLists#GET
  • /_apis/security/permissionEvaluationBatch#POST
  • /DefaultCollection/_apis/permissions#GET
  • /DefaultCollection/_apis/SecurityNamespaces#GET
  • /DefaultCollection/_apis/AccessControlLists#GET
  • /DefaultCollection/_apis/security/permissionEvaluationBatch#POST
vso.profile
  • /_apis/account#GET
  • /_apis/account/regions#GET
  • /_apis/accounts#GET
  • /_apis/projectCollections#GET
  • /_apis/profile/profiles#GET
  • /_apis/profile/UserDefaults#GET
  • /_apis/profile/regions#GET
  • /_apis/profile/georegion#GET
  • /_apis/profile/Locations#GET
  • /_apis/profile/Settings#GET
  • /_apis/profile/Attributes#GET+PATCH
  • /_apis/ClientNotification/Subscriptions#GET
  • /_apis/process/processes#GET
  • /DefaultCollection/_apis/projects#GET
  • /DefaultCollection/_apis#OPTIONS
  • /_apis/Organization/Regions#GET
vso.profile_write
  • /_apis/profile/profiles#PATCH+PUT
vso.acquisition_write
  • /*/_apis/ServiceDefinitions#GET
  • /*/_apis/projectCollections#GET
  • /*/_apis/projects#GET+POST
  • /*/_apis/operations#GET
  • /_apis/ServiceDefinitions#GET
  • /_apis/projects#GET+POST
  • /_apis/operations#GET
  • /_apis/profile/avatar#GET+POST+DELETE+PUT
  • /_apis/profile/profiles#GET+POST+PATCH
  • /_apis/profile/UserDefaults#GET+PUT
  • /_apis/accounts#GET+POST
  • /api/account#GET+POST
  • /_apis/delegatedauth/registration#GET
  • /_apis/delegatedauth/registrationsecret#GET
  • /_apis/delegatedauth/authorizations#GET
  • /_apis/UserMapping/UserAccountMappings#GET
vso.identity
  • /*/_apis/identities#GET
  • /*/_apis/groups#GET
  • /*/_apis/scopes#GET
  • /*/_apis/identitybatch#POST
  • /_apis/identities#GET
  • /_apis/groups#GET
  • /_apis/scopes#GET
  • /_apis/identitybatch#POST
  • /DefaultCollection/_apis/identities#GET
  • /DefaultCollection/_apis/groups#GET
  • /DefaultCollection/_apis/scopes#GET
  • /DefaultCollection/_apis/identitybatch#POST
vso.identity_manage
  • /Services/*/LocationService.asmx#POST
  • /*/Services/*/LocationService.asmx#POST
  • /DefaultCollection/*/Services/*/LocationService.asmx#POST
  • /*/Administration/*/LocationService.asmx#POST
  • /Services/*/Registration.asmx#POST
  • /*/Services/*/Registration.asmx#POST
  • /*/*/Administration/*/LocationService.asmx#POST
  • /_apis/identities#GET+POST+PUT+DELETE
  • /_apis/groups#GET+POST+PUT+DELETE
  • /_apis/scopes#GET+POST+PUT+DELETE+PATCH
  • /DefaultCollection/_apis/identities#GET+POST+PUT+DELETE
  • /DefaultCollection/_apis/groups#GET+POST+PUT+DELETE
  • /DefaultCollection/_apis/scopes#GET+POST+PUT+DELETE+PATCH
  • /Services/*/IdentityManagementService.asmx#POST
  • /*/Services/*/IdentityManagementService.asmx#POST
  • /Services/*/IdentityManagementService2.asmx#POST
  • /*/Services/*/IdentityManagementService2.asmx#POST
vso.hooks
  • /_apis/hooks/consumers#GET
  • /_apis/hooks/inputValuesQuery#POST
  • /_apis/hooks/notificationsQuery#POST
  • /_apis/hooks/publishers#GET
  • /_apis/hooks/publishersQuery#POST
  • /_apis/hooks/subscriptions#GET
  • /_apis/hooks/subscriptionsQuery#POST
  • /_apis/hooks/testNotifications#POST
  • /DefaultCollection/_apis/hooks/consumers#GET
  • /DefaultCollection/_apis/hooks/inputValuesQuery#POST
  • /DefaultCollection/_apis/hooks/notificationsQuery#POST
  • /DefaultCollection/_apis/hooks/publishers#GET
  • /DefaultCollection/_apis/hooks/publishersQuery#POST
  • /DefaultCollection/_apis/hooks/subscriptions#GET
  • /DefaultCollection/_apis/hooks/subscriptionsQuery#POST
  • /DefaultCollection/_apis/hooks/testNotifications#POST
vso.hooks_write
  • /_apis/hooks/subscriptions#GET+POST+PUT+DELETE
  • /DefaultCollection/_apis/hooks/subscriptions#GET+POST+PUT+DELETE
vso.hooks_interact
  • /DefaultCollection/_apis/wit/workitems#PATCH
  • /DefaultCollection/*/_apis/wit/workitemtypes/*/states#GET
vso.work
  • /_apis/tagging#GET
  • /DefaultCollection/_apis/tagging#GET
  • /DefaultCollection/_apis/wit/attachments#GET
  • /DefaultCollection/_apis/wit/fields#GET
  • /DefaultCollection/_apis/wit/workitemrelationtypes#GET
  • /DefaultCollection/_apis/wit/queries#GET
  • /DefaultCollection/_apis/wit/wiql#GET+POST
  • /DefaultCollection/_apis/wit/workitems#GET
  • /DefaultCollection/*/_apis/wit/fields#GET
  • /DefaultCollection/*/_apis/wit/classificationnodes#GET
  • /DefaultCollection/*/_apis/wit/queries#GET
  • /DefaultCollection/*/_apis/wit/wiql#GET+POST
  • /DefaultCollection/*/_apis/wit/workitemtypecategories#GET
  • /DefaultCollection/*/_apis/wit/workitemtypes#GET
  • /DefaultCollection/*/_apis/wit/workitemtypetemplate#GET
  • /DefaultCollection/*/_apis/wit/workitems#GET
  • /DefaultCollection/*/*/_apis/wit/queries#GET
  • /DefaultCollection/*/*/_apis/wit/wiql#GET+POST
  • /DefaultCollection/*/*/_apis/wit/templates#GET
  • /DefaultCollection/_apis/wit/workitemtypetemplate#GET
  • /DefaultCollection/_apis/wit/$ruleEngine#POST
  • /DefaultCollection/*/_apis/work/boards#GET
  • /DefaultCollection/*/*/_apis/work/boards#GET
  • /DefaultCollection/*/_apis/work/teamsettings#GET
  • /DefaultCollection/*/*/_apis/work/teamsettings#GET
  • /DefaultCollection/*/_apis/work/processconfiguration#GET
  • /DefaultCollection/*/_apis/work/backlogconfiguration#GET
  • /DefaultCollection/*/*/_apis/work/backlogconfiguration#GET
  • /DefaultCollection/_apis/work/boardcolumns#GET
  • /DefaultCollection/*/_apis/work/boardcolumns#GET
  • /DefaultCollection/_apis/work/boardrows#GET
  • /DefaultCollection/*/_apis/work/boardrows#GET
  • /DefaultCollection/_apis/wit/reporting/workItemRevisions#GET+POST
  • /DefaultCollection/*/_apis/wit/reporting/workItemRevisions#GET+POST
  • /DefaultCollection/_apis/wit/reporting/workItemLinks#GET
  • /DefaultCollection/*/_apis/wit/reporting/workItemLinks#GET
  • /DefaultCollection/_apis/process/processes#GET
  • /DefaultCollection/_apis/wit/artifactlinktypes#GET
  • /DefaultCollection/_apis/wit/artifacturiquery#POST
vso.work_write
  • /_apis/tagging#GET+POST+PATCH+DELETE
  • /DefaultCollection/_apis/wit/attachments#GET+POST+PUT
  • /DefaultCollection/*/_apis/wit/classificationnodes#GET+POST+DELETE+PATCH
  • /DefaultCollection/_apis/wit/queries#GET+POST+PATCH+DELETE
  • /DefaultCollection/*/_apis/wit/queries#GET+POST+PATCH+DELETE
  • /DefaultCollection/*/*/_apis/wit/queries#GET+POST+PATCH+DELETE
  • /DefaultCollection/_apis/wit/workitems#GET+POST+PATCH+DELETE
  • /DefaultCollection/_apis/wit/recyclebin#GET+PATCH+DELETE
  • /DefaultCollection/_apis/tagging#GET+POST+PATCH+DELETE
  • /DefaultCollection/*/_apis/wit/workitems#PATCH
  • /DefaultCollection/_apis/tagging#GET+POST+PATCH+DELETE
  • /DefaultCollection/*/_apis/work/boards#GET+PUT+PATCH
  • /DefaultCollection/*/*/_apis/work/boards#GET+PUT+PATCH
  • /DefaultCollection/*/_apis/wit/workitems#GET+POST+PATCH+DELETE
  • /DefaultCollection/*/_apis/wit/recyclebin#GET+PATCH+DELETE
  • /DefaultCollection/_apis/wit/$batch#POST
  • /DefaultCollection/*/_apis/work/teamsettings#GET+POST+PATCH+DELETE+PUT
  • /DefaultCollection/*/*/_apis/work/teamsettings#GET+POST+PATCH+DELETE+PUT
  • /DefaultCollection/*/_apis/wit/workitemtypetemplate#GET+POST
  • /DefaultCollection/_apis/wit/workitemtypetemplate#GET+POST
  • /DefaultCollection/*/*/_apis/wit/templates#GET+PUT+POST+DELETE
vso.work_full
  • /Services/*/LocationService.asmx#POST
  • /*/Services/*/LocationService.asmx#POST
  • /DefaultCollection/*/Services/*/LocationService.asmx#POST
  • /*/Administration/*/LocationService.asmx#POST
  • /Services/*/Registration.asmx#POST
  • /*/Services/*/Registration.asmx#POST
  • /*/*/Administration/*/LocationService.asmx#POST
  • /WorkItemTracking/*/ClientService.asmx#POST
  • /WorkItemTracking/*/ConfigurationSettingsService.asmx#POST
  • /WorkItemTracking/*/Integration.asmx#POST
  • /*/WorkItemTracking/*/ClientService.asmx#POST
  • /*/WorkItemTracking/*/ConfigurationSettingsService.asmx#POST
  • /*/WorkItemTracking/*/Integration.asmx#POST
  • /Services/*/ProcessTemplate.asmx#POST
  • /*/Services/*/ProcessTemplate.asmx#POST
  • /Services/*/TeamConfigurationService.asmx#POST
  • /*/Services/*/TeamConfigurationService.asmx#POST
  • /WorkItemTracking/*/AttachFileHandler.ashx#POST
  • /*/WorkItemTracking/*/AttachFileHandler.ashx#POST
vso.build
  • /DefaultCollection/_apis/resources/Containers#GET
  • /DefaultCollection/*/_apis/build/builds#GET
  • /DefaultCollection/*/_apis/build/definitions#GET
  • /DefaultCollection/*/_apis/build/requests#GET
  • /DefaultCollection/*/_apis/build/qualities#GET
  • /DefaultCollection/*/_apis/build/tags#GET
  • /DefaultCollection/*/_apis/build/options#GET
  • /DefaultCollection/*/_apis/build/repos#GET
  • /DefaultCollection/_apis/build/builds#GET
  • /DefaultCollection/_apis/build/queues#GET
  • /DefaultCollection/_apis/build/options#GET
  • /DefaultCollection/_apis/build/controllers#GET
  • /DefaultCollection/*/_apis/distributedtask/hubs/build/plans#GET
vso.build_execute
  • /DefaultCollection/*/_apis/build/builds#GET+PATCH+DELETE+PUT+POST
  • /DefaultCollection/*/_apis/build/requests#GET+POST+PATCH+DELETE
  • /DefaultCollection/*/_apis/build/qualities#GET+PUT+DELETE
  • /DefaultCollection/*/_apis/build/definitions#GET+POST+PUT+DELETE
  • /DefaultCollection/_apis/build/builds#GET+PATCH+DELETE+PUT+POST
  • /DefaultCollection/_apis/build/queues#GET+POST+DELETE
  • /DefaultCollection/*/_apis/distributedtask/hubs/build/plans#GET+PUT
vso.code
  • /DefaultCollection/_apis/tfvc/branches#GET
  • /DefaultCollection/*/_apis/tfvc/branches#GET
  • /DefaultCollection/_apis/tfvc/changesets#GET
  • /DefaultCollection/*/_apis/tfvc/changesets#GET
  • /DefaultCollection/_apis/tfvc/changesetsBatch#POST
  • /DefaultCollection/_apis/tfvc/labels#GET
  • /DefaultCollection/*/_apis/tfvc/labels#GET
  • /DefaultCollection/_apis/tfvc/labelItems#GET
  • /DefaultCollection/_apis/tfvc/shelvesets#GET
  • /DefaultCollection/_apis/tfvc/items#GET
  • /DefaultCollection/*/_apis/tfvc/items#GET
  • /DefaultCollection/_apis/tfvc/itemBatch#POST
  • /DefaultCollection/*/_apis/tfvc/itemBatch#POST
  • /DefaultCollection/*/*/_git/*#GET
  • /DefaultCollection/*/_git/*#GET
  • /DefaultCollection/_git/*#GET
  • /DefaultCollection/*/*/_git/_full/*#GET
  • /DefaultCollection/*/_git/_full/*#GET
  • /DefaultCollection/_git/_full/*#GET
  • /DefaultCollection/*/*/_git/_optimized/*#GET
  • /DefaultCollection/*/_git/_optimized/*#GET
  • /DefaultCollection/_git/_optimized/*#GET
  • /DefaultCollection/*/*/_git/*/git-upload-pack#POST
  • /DefaultCollection/*/_git/*/git-upload-pack#POST
  • /DefaultCollection/_git/*/git-upload-pack#POST
  • /DefaultCollection/*/*/_git/_full/*/git-upload-pack#POST
  • /DefaultCollection/*/_git/_full/*/git-upload-pack#POST
  • /DefaultCollection/_git/_full/*/git-upload-pack#POST
  • /DefaultCollection/*/*/_git/_optimized/*/git-upload-pack#POST
  • /DefaultCollection/*/_git/_optimized/*/git-upload-pack#POST
  • /DefaultCollection/_git/_optimized/*/git-upload-pack#POST
  • /DefaultCollection/*/*/_git/*/info/lfs/objects#POST
  • /DefaultCollection/*/_git/*/info/lfs/objects#POST
  • /DefaultCollection/_git/*/info/lfs/objects#POST
  • /DefaultCollection/*/*/_git/_full/*/info/lfs/objects#POST
  • /DefaultCollection/*/_git/_full/*/info/lfs/objects#POST
  • /DefaultCollection/_git/_full/*/info/lfs/objects#POST
  • /DefaultCollection/*/*/_git/_optimized/*/info/lfs/objects#POST
  • /DefaultCollection/*/_git/_optimized/*/info/lfs/objects#POST
  • /DefaultCollection/_git/_optimized/*/info/lfs/objects#POST
  • /DefaultCollection/*/*/_git/*/gvfs/*#POST
  • /DefaultCollection/*/_git/*/gvfs/*#POST
  • /DefaultCollection/_git/*/gvfs/*#POST
  • /DefaultCollection/*/*/_git/_full/*/gvfs/*#POST
  • /DefaultCollection/*/_git/_full/*/gvfs/*#POST
  • /DefaultCollection/_git/_full/*/gvfs/*#POST
  • /DefaultCollection/*/*/_git/_optimized/*/gvfs/*#POST
  • /DefaultCollection/*/_git/_optimized/*/gvfs/*#POST
  • /DefaultCollection/_git/_optimized/*/gvfs/*#POST
  • /DefaultCollection/*/_apis/git/*/repositories#GET
  • /DefaultCollection/*/_apis/git/*/repositories/*/blobs#GET
  • /DefaultCollection/*/_apis/git/*/repositories/*/commits
  • /DefaultCollection/*/_apis/git/*/repositories/*/commits/*/statuses#GET
  • /DefaultCollection/*/_apis/git/*/repositories/*/commitsBatch#POST
  • /DefaultCollection/*/_apis/git/*/repositories/*/diffs/commits#GET
  • /DefaultCollection/*/_apis/git/*/repositories/*/items#GET
  • /DefaultCollection/*/_apis/git/*/repositories/*/itemsBatch#POST
  • /DefaultCollection/*/_apis/git/*/repositories/*/filepaths#GET
  • /DefaultCollection/*/_apis/git/*/repositories/*/forks/*#GET
  • /DefaultCollection/*/_apis/git/*/repositories/*/forkSyncRequests#GET
  • /DefaultCollection/*/_apis/git/*/repositories/*/forkSyncRequests/*#GET
  • /DefaultCollection/*/_apis/git/*/repositories/*/pullrequests#GET
  • /DefaultCollection/*/_apis/git/*/repositories/*/pullrequestquery#POST
  • /DefaultCollection/*/_apis/git/*/repositories/*/pushes#GET
  • /DefaultCollection/*/_apis/git/*/repositories/*/refs#GET
  • /DefaultCollection/*/_apis/git/*/repositories/*/stats/branches#GET
  • /DefaultCollection/*/_apis/git/*/repositories/*/trees#GET
  • /DefaultCollection/*/_apis/git/favorites/refs#GET
  • /DefaultCollection/*/_apis/git/favorites/refs#POST
  • /DefaultCollection/*/_apis/git/favorites/refs#PUT
  • /DefaultCollection/*/_apis/git/repositories#GET
  • /DefaultCollection/*/_apis/git/repositories/*/blobs#GET
  • /DefaultCollection/*/_apis/git/repositories/*/commits
  • /DefaultCollection/*/_apis/git/repositories/*/commits/*/statuses#GET
  • /DefaultCollection/*/_apis/git/repositories/*/commitsBatch#POST
  • /DefaultCollection/*/_apis/git/repositories/*/diffs/commits#GET
  • /DefaultCollection/*/_apis/git/repositories/*/items#GET
  • /DefaultCollection/*/_apis/git/repositories/*/itemsBatch#POST
  • /DefaultCollection/*/_apis/git/repositories/*/filepaths#GET
  • /DefaultCollection/*/_apis/git/repositories/*/forks/*#GET
  • /DefaultCollection/*/_apis/git/repositories/*/forkSyncRequests#GET
  • /DefaultCollection/*/_apis/git/repositories/*/forkSyncRequests/*#GET
  • /DefaultCollection/*/_apis/git/repositories/*/pullrequests#GET
  • /DefaultCollection/*/_apis/git/repositories/*/pullrequestquery#POST
  • /DefaultCollection/*/_apis/git/repositories/*/pushes#GET
  • /DefaultCollection/*/_apis/git/repositories/*/refs#GET
  • /DefaultCollection/*/_apis/git/repositories/*/stats/branches#GET
  • /DefaultCollection/*/_apis/git/repositories/*/trees#GET
  • /DefaultCollection/*/_apis/git/repositories/*/limitedRefCriteria#GET
  • /DefaultCollection/*/_apis/git/*/repositories/*/objects#GET
  • /DefaultCollection/*/_apis/git/repositories/*/objects#GET
  • /DefaultCollection/_apis/git/*/repositories#GET
  • /DefaultCollection/_apis/git/*/repositories/*/blobs#GET
  • /DefaultCollection/_apis/git/*/repositories/*/commits
  • /DefaultCollection/_apis/git/*/repositories/*/commits/*/statuses#GET
  • /DefaultCollection/_apis/git/*/repositories/*/commitsBatch#POST
  • /DefaultCollection/_apis/git/*/repositories/*/diffs/commits#GET
  • /DefaultCollection/_apis/git/*/repositories/*/items#GET
  • /DefaultCollection/_apis/git/*/repositories/*/itemsBatch#POST
  • /DefaultCollection/_apis/git/*/repositories/*/filepaths#GET
  • /DefaultCollection/_apis/git/*/repositories/*/forks/*#GET
  • /DefaultCollection/_apis/git/*/repositories/*/forkSyncRequests#GET
  • /DefaultCollection/_apis/git/*/repositories/*/forkSyncRequests/*#GET
  • /DefaultCollection/_apis/git/*/repositories/*/pullrequests#GET
  • /DefaultCollection/_apis/git/*/repositories/*/pullrequestquery#POST
  • /DefaultCollection/_apis/git/*/repositories/*/pushes#GET
  • /DefaultCollection/_apis/git/*/repositories/*/refs#GET
  • /DefaultCollection/_apis/git/*/repositories/*/stats/branches#GET
  • /DefaultCollection/_apis/git/*/repositories/*/trees#GET
  • /DefaultCollection/_apis/git/repositories#GET
  • /DefaultCollection/_apis/git/repositories/*/blobs#GET
  • /DefaultCollection/_apis/git/repositories/*/commits
  • /DefaultCollection/_apis/git/repositories/*/commits/*/statuses#GET
  • /DefaultCollection/_apis/git/repositories/*/commitsBatch#POST
  • /DefaultCollection/_apis/git/repositories/*/diffs/commits#GET
  • /DefaultCollection/_apis/git/repositories/*/items#GET
  • /DefaultCollection/_apis/git/repositories/*/itemsBatch#POST
  • /DefaultCollection/_apis/git/repositories/*/filepaths#GET
  • /DefaultCollection/_apis/git/repositories/*/forks/*#GET
  • /DefaultCollection/_apis/git/repositories/*/forkSyncRequests#GET
  • /DefaultCollection/_apis/git/repositories/*/forkSyncRequests/*#GET
  • /DefaultCollection/_apis/git/repositories/*/pullrequests#GET
  • /DefaultCollection/_apis/git/repositories/*/pullrequestquery#POST
  • /DefaultCollection/_apis/git/repositories/*/pushes#GET
  • /DefaultCollection/_apis/git/repositories/*/refs#GET
  • /DefaultCollection/_apis/git/repositories/*/stats/branches#GET
  • /DefaultCollection/_apis/git/repositories/*/trees#GET
  • /DefaultCollection/_apis/git/repositories/*/limitedRefCriteria#GET
  • /DefaultCollection/_apis/git/*/repositories/*/objects#GET
  • /DefaultCollection/_apis/git/repositories/*/objects#GET
  • /DefaultCollection/*/_apis/git/pullRequests#GET
  • /DefaultCollection/_apis/codereview/reviews#GET
  • /DefaultCollection/*/_apis/codereview/reviews#GET
  • /DefaultCollection/*/_apis/codereview/reviewsbatch#POST
  • /DefaultCollection/*/_apis/codereview/settings#GET
  • /DefaultCollection/_apis/visits/artifactVisitsBatch#POST
  • /DefaultCollection/_apis/visits/artifactStatsBatch#POST
  • /DefaultCollection/*/_apis/policy/Evaluations#GET
vso.code_write
  • /DefaultCollection/_apis/tfvc/changesets#GET+POST
  • /DefaultCollection/*/_apis/tfvc/changesets#GET+POST
  • /DefaultCollection/*/*/_git/*#POST+PUT+PATCH+DELETE
  • /DefaultCollection/*/_git/*#POST+PUT+PATCH+DELETE
  • /DefaultCollection/_git/*#POST+PUT+PATCH+DELETE
  • /DefaultCollection/*/*/_git/_full/*#POST+PUT+PATCH+DELETE
  • /DefaultCollection/*/_git/_full/*#POST+PUT+PATCH+DELETE
  • /DefaultCollection/_git/_full/*#POST+PUT+PATCH+DELETE
  • /DefaultCollection/*/*/_git/_optimized/*#POST+PUT+PATCH+DELETE
  • /DefaultCollection/*/_git/_optimized/*#POST+PUT+PATCH+DELETE
  • /DefaultCollection/_git/_optimized/*#POST+PUT+PATCH+DELETE
  • /DefaultCollection/*/_apis/git/*/repositories/*/pullrequests#POST+PUT+PATCH+DELETE
  • /DefaultCollection/*/_apis/git/*/repositories/*/pushes#POST
  • /DefaultCollection/*/_apis/git/*/repositories/*/refs#POST+PUT+PATCH+DELETE
  • /DefaultCollection/*/_apis/git/*/repositories/*/commits/*/statuses#GET+POST
  • /DefaultCollection/*/_apis/git/*/repositories/*/forkSyncRequests#POST
  • /DefaultCollection/*/_apis/git/*/repositories/*/forkSyncRequests/*#POST
  • /DefaultCollection/*/_apis/git/repositories/*/pullrequests#POST+PUT+PATCH+DELETE
  • /DefaultCollection/*/_apis/git/repositories/*/pushes#POST
  • /DefaultCollection/*/_apis/git/repositories/*/refs#POST+PUT+PATCH+DELETE
  • /DefaultCollection/*/_apis/git/repositories/*/commits/*/statuses#GET+POST
  • /DefaultCollection/*/_apis/git/repositories/*/forkSyncRequests#POST
  • /DefaultCollection/*/_apis/git/repositories/*/forkSyncRequests/*#POST
  • /DefaultCollection/*/_apis/git/*/repositories/*/objects#PUT
  • /DefaultCollection/*/_apis/git/repositories/*/objects#PUT
  • /DefaultCollection/_apis/git/*/repositories/*/pullrequests#POST+PUT+PATCH+DELETE
  • /DefaultCollection/_apis/git/*/repositories/*/pushes#POST
  • /DefaultCollection/_apis/git/*/repositories/*/refs#POST+PUT+PATCH+DELETE
  • /DefaultCollection/_apis/git/*/repositories/*/commits/*/statuses#GET+POST
  • /DefaultCollection/_apis/git/*/repositories/*/forkSyncRequests#POST
  • /DefaultCollection/_apis/git/*/repositories/*/forkSyncRequests/*#POST
  • /DefaultCollection/_apis/git/repositories/*/pullrequests#POST+PUT+PATCH+DELETE
  • /DefaultCollection/_apis/git/repositories/*/pushes#POST
  • /DefaultCollection/_apis/git/repositories/*/refs#POST+PUT+PATCH+DELETE
  • /DefaultCollection/_apis/git/repositories/*/commits/*/statuses#GET+POST
  • /DefaultCollection/_apis/git/repositories/*/forkSyncRequests#POST
  • /DefaultCollection/_apis/git/repositories/*/forkSyncRequests/*#POST
  • /DefaultCollection/_apis/git/*/repositories/*/objects#PUT
  • /DefaultCollection/_apis/git/repositories/*/objects#PUT
  • /DefaultCollection/*/_apis/codereview/reviews#POST+PUT+PATCH+DELETE
  • /DefaultCollection/*/_apis/codereview/settings#POST+PUT
  • /DefaultCollection/_apis/visits/artifactVisits#PUT
  • /DefaultCollection/*/_apis/policy/Evaluations#PATCH
vso.code_manage
  • /DefaultCollection/*/_apis/git/repositories#POST+PATCH+DELETE
  • /DefaultCollection/*/_apis/git/*/repositories#POST+PATCH+DELETE
  • /DefaultCollection/*/_apis/git/repositories/*/limitedRefCriteria#PUT
  • /DefaultCollection/_apis/git/repositories#POST+PATCH+DELETE
  • /DefaultCollection/_apis/git/*/repositories#POST+PATCH+DELETE
  • /DefaultCollection/_apis/git/repositories/*/limitedRefCriteria#PUT
vso.code_full
  • /Services/*/LocationService.asmx#POST
  • /*/Services/*/LocationService.asmx#POST
  • /DefaultCollection/*/Services/*/LocationService.asmx#POST
  • /*/Administration/*/LocationService.asmx#POST
  • /Services/*/Registration.asmx#POST
  • /*/Services/*/Registration.asmx#POST
  • /*/*/Administration/*/LocationService.asmx#POST
  • /VersionControl/*/integration.asmx#POST
  • /VersionControl/*/repository.asmx#POST
  • /*/VersionControl/*/integration.asmx#POST
  • /*/VersionControl/*/repository.asmx#POST
  • /VersionControl/*/item.ashx#POST
  • /VersionControl/*/upload.ashx#POST
  • /*/VersionControl/*/item.ashx#POST
  • /*/VersionControl/*/upload.ashx#POST
vso.code_status
  • /DefaultCollection/_apis/git/repositories/*/commits/*/statuses#GET+POST
  • /DefaultCollection/*/_apis/git/repositories/*/commits/*/statuses#GET+POST
  • /DefaultCollection/_apis/git/repositories/*/pullrequests/*/statuses#GET+POST
  • /DefaultCollection/*/_apis/git/repositories/*/pullrequests/*/statuses#GET+POST
  • /DefaultCollection/_apis/git/repositories/*/pullrequests/*/iterations/*/statuses#GET+POST
  • /DefaultCollection/*/_apis/git/repositories/*/pullrequests/*/iterations/*/statuses#GET+POST
vso.chat_write
  • /DefaultCollection/_apis/chat/rooms#GET
  • /DefaultCollection/_apis/chat/rooms/*/messages#GET+POST+PATCH+DELETE
  • /DefaultCollection/_apis/chat/rooms/*/users#GET+PUT+DELETE
vso.chat_manage
  • /DefaultCollection/_apis/chat/rooms#GET+POST+PATCH+PUT+DELETE
vso.agentpools
  • /_apis/distributedtask/packages/agent#GET
  • /_apis/distributedtask/pools#GET
  • /_apis/distributedtask/pools/*/agents#GET
  • /_apis/distributedtask/pools/*/jobrequests#GET
  • /_apis/distributedtask/queues#GET
  • /_apis/distributedtask/tasks#GET
  • /DefaultCollection/_apis/distributedtask/packages/agent#GET
  • /DefaultCollection/_apis/distributedtask/pools#GET
  • /DefaultCollection/_apis/distributedtask/pools/*/agents#GET
  • /DefaultCollection/_apis/distributedtask/pools/*/jobrequests#GET
  • /DefaultCollection/_apis/distributedtask/queues#GET
  • /DefaultCollection/*/_apis/distributedtask/queues#GET
  • /DefaultCollection/_apis/distributedtask/tasks#GET
vso.agentpools_manage
  • /_apis/distributedtask/packages/agent#GET
  • /_apis/distributedtask/pools#DELETE+GET+PATCH+POST
  • /_apis/distributedtask/pools/*/agents#DELETE+GET+PATCH+POST+PUT
  • /_apis/distributedtask/pools/*/jobrequests#GET
  • /_apis/distributedtask/queues#DELETE+GET+PATCH+POST+PUT
  • /_apis/distributedtask/tasks#DELETE+GET+PATCH+POST+PUT
  • /DefaultCollection/_apis/distributedtask/packages/agent#GET
  • /DefaultCollection/_apis/distributedtask/pools#DELETE+GET+PATCH+POST
  • /DefaultCollection/_apis/distributedtask/pools/*/agents#DELETE+GET+PATCH+POST+PUT
  • /DefaultCollection/_apis/distributedtask/pools/*/jobrequests#GET
  • /DefaultCollection/_apis/distributedtask/queues#DELETE+GET+PATCH+POST
  • /DefaultCollection/*/_apis/distributedtask/queues#DELETE+GET+PATCH+POST+PUT
  • /DefaultCollection/_apis/distributedtask/tasks#DELETE+GET+PATCH+POST+PUT
vso.agentpools_listen
  • /_apis/distributedtask/pools/*/jobrequests#GET+PATCH+DELETE
  • /_apis/distributedtask/pools/*/messages#GET+DELETE
  • /_apis/distributedtask/pools/*/sessions#GET+POST+DELETE
  • /_apis/distributedtask/pools/*/agents/*/updates#PUT
  • /DefaultCollection/_apis/distributedtask/pools/*/jobrequests#GET+PATCH+DELETE
  • /DefaultCollection/_apis/distributedtask/pools/*/messages#GET+DELETE
  • /DefaultCollection/_apis/distributedtask/pools/*/sessions#GET+POST+DELETE
  • /DefaultCollection/_apis/distributedtask/pools/*/agents/*/updates#PUT
vso.governance.extension_write
  • /_apis/governance/components#GET
  • /_apis/governance/products#GET
  • /_apis/governance/products/*/registrations/*/policyStatuses#PUT
vso.packaging
  • /DefaultCollection/_apis/packaging#HEAD+GET
  • /DefaultCollection/_packaging#HEAD+GET
vso.packaging_write
  • /DefaultCollection/_apis/packaging#HEAD+GET+POST+PUT
  • /DefaultCollection/_packaging#HEAD+GET+POST+PUT
  • /DefaultCollection/_packaging/*/nuget/v2#DELETE
  • /DefaultCollection/_packaging/*/npm#DELETE
  • /DefaultCollection/_apis/packaging/feeds/*/maven/groups/*/artifacts/*/versions#DELETE
  • /DefaultCollection/_apis/packaging/*/packages/*/versions#DELETE
vso.packaging_manage
  • /DefaultCollection/_apis/packaging#HEAD+GET+PATCH+POST+PUT+DELETE
  • /DefaultCollection/_packaging#HEAD+GET+PATCH+POST+PUT+DELETE
vso.oss
  • /DefaultCollection/_apis/oss/*#GET
vso.oss_write
  • /DefaultCollection/_apis/oss/Requests#POST+PUT+PATCH
  • /DefaultCollection/_apis/oss/Versions#PATCH
  • /DefaultCollection/_apis/oss/Validation#POST
vso.oss_manage
  • /DefaultCollection/_apis/oss/*#POST+PUT+PATCH+DELETE
vso.oss.extension_read
  • /DefaultCollection/_apis/oss/ExtensionData/*#GET
vso.oss.extension_write
  • /DefaultCollection/_apis/oss/ExtensionData/*#POST+PUT+PATCH+DELETE
vso.test
  • /DefaultCollection/_apis/test/suites#GET
  • /DefaultCollection/*/_apis/test/plans#GET
  • /DefaultCollection/*/_apis/test/runs#GET
  • /DefaultCollection/*/_apis/test/extensionFields#GET
  • /DefaultCollection/*/_apis/test/suites#GET
  • /DefaultCollection/*/_apis/test/results#GET
  • /DefaultCollection/*/_apis/test/testSettings#GET
  • /DefaultCollection/*/_apis/test/codeCoverage#GET
  • /DefaultCollection/*/_apis/test/configurations#GET
  • /DefaultCollection/*/_apis/test/variables#GET
  • /DefaultCollection/*/_apis/test/cloneOperation#GET
  • /DefaultCollection/*/_apis/test/session#GET
  • /DefaultCollection/*/_apis/test/suiteEntry#GET
  • /DefaultCollection/*/_apis/test/ResultRetentionSettings#GET
  • /DefaultCollection/*/_apis/test/ResultSummaryByRelease#GET
  • /DefaultCollection/*/_apis/test/ResultSummaryByBuild#GET
  • /DefaultCollection/*/_apis/test/ResultSummaryByRequirement#GET
  • /DefaultCollection/*/_apis/test/ResultDetailsByRelease#GET
  • /DefaultCollection/*/_apis/test/ResultDetailsByBuild#GET
  • /DefaultCollection/*/_apis/test/TestMethods#GET
  • /DefaultCollection/*/_apis/test/Points#GET
  • /DefaultCollection/*/*/_apis/test/session#GET
vso.test_write
  • /DefaultCollection/*/_apis/test/plans#GET+POST+PATCH+DELETE
  • /DefaultCollection/*/_apis/test/suites#GET+POST+PATCH+DELETE
  • /DefaultCollection/*/_apis/test/runs#GET+POST+PATCH+DELETE
  • /DefaultCollection/*/_apis/test/results#GET+POST
  • /DefaultCollection/*/_apis/test/extensionFields#GET+POST
  • /DefaultCollection/*/_apis/test/testSettings#GET+POST+DELETE
  • /DefaultCollection/*/_apis/test/codeCoverage#GET+POST
  • /DefaultCollection/*/_apis/test/configurations#GET+POST+PATCH+DELETE
  • /DefaultCollection/*/_apis/test/variables#GET+POST+PATCH+DELETE
  • /DefaultCollection/*/_apis/test/cloneOperation#GET+POST
  • /DefaultCollection/*/_apis/test/session#GET+POST+PATCH
  • /DefaultCollection/*/_apis/test/suiteEntry#GET+PATCH
  • /DefaultCollection/*/_apis/test/ResultRetentionSettings#GET+PATCH
  • /DefaultCollection/*/_apis/test/ResultSummaryByRelease#GET+POST
  • /DefaultCollection/*/_apis/test/ResultSummaryByRequirement#GET+POST
  • /DefaultCollection/*/_apis/test/TestMethods#GET+POST+DELETE
  • /DefaultCollection/*/_apis/test/Points#GET+POST+PATCH+DELETE
  • /DefaultCollection/*/*/_apis/test/session#GET+POST+PATCH
vso.loadtest
  • /_apis/clt/testdrops
  • /_apis/clt/testruns
  • /_apis/clt/testruns/*/errors
  • /_apis/clt/testruns/*/messages
  • /_apis/clt/testruns/*/results
  • /_apis/clt/testruns/*/counterinstances
  • /_apis/clt/testruns/*/countersamples
  • /_apis/clt/apm
  • /_apis/clt/configuration
  • /_apis/clt/agentgroups
  • /_apis/clt/agentgroups/*/agents
vso.loadtest_write
  • /_apis/clt/testdrops#GET+POST
  • /_apis/clt/testruns#GET+POST+PATCH
  • /_apis/clt/agentgroups#GET+POST+PATCH+DELETE
  • /_apis/clt/agentgroups/*/agents#GET+POST+PATCH+DELETE
vso.licensing
  • /_apis/licensing/clientrights
  • /_apis/licensing/ExtensionEntitlements/*/*#GET
  • /_apis/licensing/Usage#GET
  • /_apis/licensing/AccountAssignedExtensions#GET
vso.extension
  • /_apis/ExtensionManagement/InstalledExtensions#GET
  • /DefaultCollection/_apis/ExtensionManagement/InstalledExtensions#GET
vso.extension_manage
  • /_apis/ExtensionManagement/InstalledExtensions#GET+POST+PATCH+DELETE+PUT
  • /DefaultCollection/_apis/ExtensionManagement/InstalledExtensions#GET+POST+PATCH+DELETE+PUT
  • /_apis/ExtensionManagement/InstalledExtensionsByName#GET+POST+PATCH+DELETE+PUT
  • /DefaultCollection/_apis/ExtensionManagement/InstalledExtensionsByName#GET+POST+PATCH+DELETE+PUT
  • /_apis/ExtensionManagement/RequestedExtensions#GET+POST+PATCH+DELETE+PUT
  • /DefaultCollection/_apis/ExtensionManagement/RequestedExtensions#GET+POST+PATCH+DELETE+PUT
  • /_apis/ExtensionManagement/AcquisitionOptions#GET
  • /DefaultCollection/_apis/ExtensionManagement/AcquisitionOptions#GET
  • /_apis/ExtensionManagement/AcquisitionRequests#POST
  • /DefaultCollection/_apis/ExtensionManagement/AcquisitionRequests#POST
vso.extension.data
  • /_apis/ExtensionManagement/InstalledExtensions/*/Data#GET
  • /DefaultCollection/_apis/ExtensionManagement/InstalledExtensions/*/Data#GET
  • /_apis/ExtensionManagement/InstalledExtensions/*/*/Data#GET
  • /DefaultCollection/_apis/ExtensionManagement/InstalledExtensions/*/*/Data#GET
  • /_apis/Contribution/InstalledApps#GET
  • /DefaultCollection/_apis/Contribution/InstalledApps#GET
  • /_apis/ExtensionManagement/InstalledExtensions/*/*/ExtensionDataCollectionQuery#POST
  • /DefaultCollection/_apis/ExtensionManagement/InstalledExtensions/*/*/ExtensionDataCollectionQuery#POST
vso.extension.data_write
  • /_apis/ExtensionManagement/InstalledExtensions/*/Data#GET+POST+PATCH+DELETE+PUT
  • /DefaultCollection/_apis/ExtensionManagement/InstalledExtensions/*/Data#GET+POST+PATCH+DELETE+PUT
  • /_apis/ExtensionManagement/InstalledExtensions/*/*/Data#GET+POST+PATCH+DELETE+PUT
  • /DefaultCollection/_apis/ExtensionManagement/InstalledExtensions/*/*/Data#GET+POST+PATCH+DELETE+PUT
vso.extension.default
  • /_apis/Contribution/InstalledApps#GET
  • /DefaultCollection/_apis/Contribution/InstalledApps#GET
  • /_apis/Contribution/nodes/query#POST
  • /DefaultCollection/_apis/Contribution/nodes/query#POST
vso.extension.preview
  • /_apis/ExtensionManagement/InstalledExtensions/*/Data#GET+POST+PATCH+DELETE+PUT
  • /DefaultCollection/_apis/ExtensionManagement/InstalledExtensions/*/Data#GET+POST+PATCH+DELETE+PUT
vso.commerce.write
  • /_apis/Commerce/*#GET+POST+PATCH+PUT
  • /_apis/Commerce/Subscription/*/*#GET+PUT+POST
vso.gallery
  • /_apis/gallery/publishers#GET
  • /_apis/gallery/extensions#GET
vso.gallery_acquire
  • /_apis/gallery/acquisitionrequests#POST
  • /_apis/gallery/acquisitionoptions#GET+POST
vso.gallery_publish
  • /_apis/gallery/publishers/*/extensions#POST+PUT+DELETE
  • /_apis/gallery/publisher/*/extension/*/accountsbyname#POST+DELETE
  • /_apis/gallery/extensions#POST+PUT+DELETE
  • /_apis/gallery/extensions/*/accounts#POST+DELETE
vso.gallery_manage
  • /_apis/gallery/publishers#POST+PUT+DELETE
vso.entitlements
  • /_apis/licensing/entitlements#GET
preview_msdn_licensing
  • /_apis/licensing/msdn/me
user_impersonation
  • /_signedin#GET+POST
signout
  • /_signout
app_token
  • /*#*
vso.release
  • /DefaultCollection/*/_apis/release/definitions#GET
  • /DefaultCollection/*/_apis/release/definitions/*/revisions#GET
  • /DefaultCollection/*/_apis/release/releases#GET
  • /DefaultCollection/*/_apis/release/releases/*/workitems#GET
  • /DefaultCollection/*/_apis/release/approvals#GET
  • /DefaultCollection/*/_apis/release/releases/*/manualInterventions#GET
  • /DefaultCollection/*/_apis/release/deployments#GET+POST
  • /DefaultCollection/*/_apis/distributedtask/hubs/release/plans#GET
vso.release_execute
  • /DefaultCollection/*/_apis/release/definitions#GET+POST+PUT
  • /DefaultCollection/*/_apis/release/definitions/*/revisions#GET
  • /DefaultCollection/*/_apis/release/releases#GET+POST+PATCH+PUT
  • /DefaultCollection/*/_apis/release/releases/*/workitems#GET
  • /DefaultCollection/*/_apis/release/releases/*/environments#PATCH
  • /DefaultCollection/*/_apis/release/approvals#GET
  • /DefaultCollection/*/_apis/release/releases/*/manualInterventions#GET
  • /DefaultCollection/*/_apis/release/deployments#GET+POST
vso.release_manage
  • /DefaultCollection/*/_apis/release/definitions#GET+POST+PUT+DELETE
  • /DefaultCollection/*/_apis/release/definitions/*/revisions#GET
  • /DefaultCollection/*/_apis/release/releases#GET+POST+PATCH+PUT+DELETE
  • /DefaultCollection/*/_apis/release/releases/*/workitems#GET
  • /DefaultCollection/*/_apis/release/releases/*/environments#PATCH
  • /DefaultCollection/*/_apis/release/approvals#GET+PATCH
  • /DefaultCollection/*/_apis/release/releases/*/manualInterventions#GET+PATCH
  • /DefaultCollection/*/_apis/release/deployments#GET+POST
vso.release_logs
  • /DefaultCollection/*/_apis/release/releases/*/logs#GET
  • /DefaultCollection/*/_apis/release/releases/*/environments/*/tasks/*/logs#GET
  • /DefaultCollection/*/_apis/release/releases/*/environments/*/deployPhases/*/tasks/*/logs#GET
vso.machinegroup_manage
  • /DefaultCollection/*/_apis/distributedtask/machinegroups/*#GET+POST+DELETE+PATCH
  • /DefaultCollection/*/_apis/distributedtask/deploymentgroups/*#GET+POST+DELETE+PATCH+PUT
vso.live_updates
  • /signalr#GET+POST
vso.taskgroups
  • /DefaultCollection/*/_apis/distributedtask/taskgroups#GET
  • /DefaultCollection/*/_apis/distributedtask/taskgroups/*/revisions#GET
vso.taskgroups_add
  • /DefaultCollection/*/_apis/distributedtask/taskgroups#POST
vso.taskgroups_manage
  • /DefaultCollection/*/_apis/distributedtask/taskgroups#GET+POST+PUT+DELETE
vso.serviceendpoint
  • /DefaultCollection/*/_apis/distributedtask/serviceendpoints#GET
  • /DefaultCollection/_apis/distributedtask/serviceendpointtypes#GET
vso.serviceendpoint_query
  • /DefaultCollection/*/_apis/distributedtask/serviceendpointproxy#POST
vso.serviceendpoint_manage
  • /DefaultCollection/*/_apis/distributedtask/serviceendpoints#GET+POST+PUT+DELETE
vso.drop
  • /DefaultCollection/_apis/drop/client#HEAD
  • /DefaultCollection/_apis/blob/blobs/*#GET
  • /DefaultCollection/_apis/blob/blobsbatch#POST
  • /DefaultCollection/_apis/dedup/chunks/*#GET
  • /DefaultCollection/_apis/dedup/nodes/*#GET
  • /DefaultCollection/_apis/dedup/urls/*#POST
  • /DefaultCollection/_apis/drop/drop#OPTIONS
  • /DefaultCollection/_apis/drop/drop/*#GET
  • /DefaultCollection/_apis/drop/fetch/*#GET+POST
  • /DefaultCollection/_apis/drop/drops/*#OPTIONS+GET
  • /DefaultCollection/_apis/drop/manifests/*#OPTIONS+GET
vso.drop_write
  • /DefaultCollection/_apis/blob/blobs#OPTIONS
  • /DefaultCollection/_apis/blob/blobs/*#POST
  • /DefaultCollection/_apis/dedup/chunks/*#PUT+POST
  • /DefaultCollection/_apis/dedup/nodes/*#PUT+POST
  • /DefaultCollection/_apis/drop/drop/*#PUT+POST+PATCH
  • /DefaultCollection/_apis/drop/drops/*#OPTIONS+PUT+POST+PATCH
  • /DefaultCollection/_apis/drop/manifests/*#OPTIONS+POST
vso.drop_manage
  • /DefaultCollection/_apis/drop/drop/*#DELETE
  • /DefaultCollection/_apis/drop/drops/*#DELETE
vso.buildcache
  • /_apis/buildcache/cachedeterminismguid/*#GET
  • /_apis/buildcache/contenthashlist#OPTIONS
  • /_apis/buildcache/contenthashlist/*#GET
  • /_apis/buildcache/selector#OPTIONS
  • /_apis/buildcache/selector/*#GET
  • /_apis/blob/blob/referencesbatch#POST
vso.buildcache_write
  • /_apis/buildcache/contenthashlist/*#POST
  • /_apis/buildcache/incorporateStrongFingeprint/*#PUT
  • /_apis/blob/blobs#OPTIONS
  • /_apis/blob/blobs/*#POST
vso.authorization_grant
vso.project
  • /DefaultCollection/_apis/projects#GET
vso.project_write
  • /DefaultCollection/_apis/projects#PATCH
vso.project_manage
  • /Services/*/LocationService.asmx#POST
  • /*/Services/*/LocationService.asmx#POST
  • /DefaultCollection/*/Services/*/LocationService.asmx#POST
  • /*/Administration/*/LocationService.asmx#POST
  • /Services/*/Registration.asmx#POST
  • /*/Services/*/Registration.asmx#POST
  • /*/*/Administration/*/LocationService.asmx#POST
  • /DefaultCollection/_apis/projects#POST+DELETE
  • /Services/*/CommonStructureService.asmx#POST
  • /*/Services/*/CommonStructureService.asmx#POST
  • /TeamFoundation/Administration/*/CatalogService.asmx#POST
  • /*/TeamFoundation/Administration/*/CatalogService.asmx#POST
  • /*/*/TeamFoundation/Administration/*/CatalogService.asmx#POST
  • /*/*/*/TeamFoundation/Administration/*/CatalogService.asmx#POST
vso.symbols
  • /DefaultCollection/_apis/symbol/symsrv#OPTIONS
  • /DefaultCollection/_apis/symbol/symsrv/*#GET
  • /DefaultCollection/_apis/symbol/debugentries#OPTIONS
  • /DefaultCollection/_apis/symbol/debugentries/*#GET
  • /DefaultCollection/_apis/symbol/requests#OPTIONS+GET
vso.symbols_write
  • /DefaultCollection/_apis/symbol/requests#POST
  • /DefaultCollection/_apis/symbol/requests/*#POST+PATCH
  • /DefaultCollection/_apis/blob/blobs#OPTIONS
  • /DefaultCollection/_apis/blob/blobs/*#POST
vso.symbols_manage
  • /DefaultCollection/_apis/symbol/requests/*#DELETE
vso.analytics
  • /DefaultCollection/_odata/*#GET
  • /DefaultCollection/*/_odata/*#GET
vso.identitypicker
  • /_apis/IdentityPicker/identities#POST
  • /_apis/IdentityPicker/identities/*/avatar#GET
  • /DefaultCollection/_apis/IdentityPicker/identities#POST
  • /DefaultCollection/_apis/IdentityPicker/identities/*/avatar#GET
vso.dashboards
  • /DefaultCollection/*/*/_apis/dashboard/dashboards#HEAD+GET
  • /DefaultCollection/*/*/_apis/dashboard/dashboards/*/widgets#HEAD+GET
vso.dashboards_manage
  • /DefaultCollection/*/*/_apis/dashboard/dashboards#HEAD+GET+POST+DELETE
  • /DefaultCollection/*/*/_apis/dashboard/dashboards/*/widgets#HEAD+GET+POST+PUT+PATCH+DELETE
vso.connected_server
  • /_apis/Commerce/CommercePackage#GET
  • /_apis/Commerce/CommercePackage/*#GET
vso.notification
  • /_apis/notification/EventTypes#GET
  • /_apis/notification/EventTypes/*/fieldValuesQuery#POST
  • /_apis/notification/Subscriptions#GET
  • /_apis/notification/SubscriptionQuery#POST
  • /_apis/notification/Follows#GET
  • /_apis/notification/SubscriptionTemplates#GET
  • /_apis/notification/StatisticsQuery#POST
  • /DefaultCollection/_apis/notification/EventTypes#GET
  • /DefaultCollection/_apis/notification/EventTypes/*/fieldValuesQuery#POST
  • /DefaultCollection/_apis/notification/Subscriptions#GET
  • /DefaultCollection/_apis/notification/SubscriptionQuery#POST
  • /DefaultCollection/_apis/notification/Follows#GET
  • /DefaultCollection/_apis/notification/SubscriptionTemplates#GET
  • /DefaultCollection/_apis/notification/StatisticsQuery#POST
vso.notification_write
  • /_apis/notification/Subscriptions#GET+PATCH+POST+DELETE+PUT
  • /DefaultCollection/_apis/notification/Subscriptions#GET+PATCH+POST+DELETE+PUT
  • /_apis/notification/SubscriptionEvaluationRequest#GET+POST
  • /DefaultCollection/_apis/notification/SubscriptionEvaluationRequest#GET+POST
  • /_apis/notification/Follows#GET+POST+DELETE
  • /DefaultCollection/_apis/notification/Follows#GET+POST+DELETE
vso.notification_manage
  • /_apis/notification/BatchNotificationOperations#POST
  • /DefaultCollection/_apis/notification/BatchNotificationOperations#POST
vso.notification_publish
  • /_apis/notification/Events#POST
  • /DefaultCollection/_apis/notification/Events#POST
vso.settings
  • /_apis/Settings/*#GET
  • /DefaultCollection/_apis/Settings/*#GET
vso.settings_write
  • /_apis/Settings/*#GET+PUT+PATCH+DELETE
  • /DefaultCollection/_apis/Settings/*#GET+PUT+PATCH+DELETE
vso.proxy
  • /Services/v4.0/item.ashx
  • /Services/v4.0/FileHandlerService.asmx#POST
  • /TeamFoundation/Administration/v3.0/LocationService.asmx#POST
  • /Services/v3.0/LocationService.asmx#POST
  • /DefaultCollection/Services/v4.0/item.ashx
  • /DefaultCollection/Services/v4.0/FileHandlerService.asmx#POST
  • /DefaultCollection/Services/v3.0/LocationService.asmx#POST
  • /*/*/*/_git/*#GET
  • /*/*/_git/*#GET
  • /*/_git/*#GET
  • /*/*/*/_git/_full/*#GET
  • /*/*/_git/_full/*#GET
  • /*/_git/_full/*#GET
  • /*/*/*/_git/*/git-upload-pack#POST
  • /*/*/_git/*/git-upload-pack#POST
  • /*/_git/*/git-upload-pack#POST
  • /*/*/*/_git/_full/*/git-upload-pack#POST
  • /*/*/_git/_full/*/git-upload-pack#POST
  • /*/_git/_full/*/git-upload-pack#POST
  • /*/*/*/_git/*/gvfs/*#POST
  • /*/*/_git/*/gvfs/*#POST
  • /*/_git/*/gvfs/*#POST
  • /*/*/*/_git/_full/*/gvfs/*#POST
  • /*/*/_git/_full/*/gvfs/*#POST
  • /*/_git/_full/*/gvfs/*#POST
vso.graph
  • /_apis/graph/descriptors/*#GET
  • /_apis/graph/groups/*#GET
  • /_apis/graph/subjectlookup#POST
  • /_apis/graph/memberships/*#GET
  • /_apis/graph/memberships/*/*#GET+HEAD
  • /_apis/graph/membershipstates/*#GET
  • /_apis/graph/storagekeys/*#GET
  • /_apis/graph/scopes/*#GET
  • /_apis/graph/subjects/*#GET
  • /_apis/graph/users/*#GET
  • /*/_apis/graph/descriptors/*#GET
  • /*/_apis/graph/groups/*#GET
  • /*/_apis/graph/subjectlookup#POST
  • /*/_apis/graph/memberships/*#GET
  • /*/_apis/graph/memberships/*/*#GET+HEAD
  • /*/_apis/graph/membershipstates/*#GET
  • /*/_apis/graph/storagekeys/*#GET
  • /*/_apis/graph/scopes/*#GET
  • /*/_apis/graph/subjects/*#GET
  • /*/_apis/graph/users/*#GET
vso.graph_manage
  • /_apis/graph/groups/*#POST+PATCH+DELETE
  • /_apis/graph/memberships/*/*#PUT+DELETE
  • /_apis/graph/scopes/*#POST+PATCH+DELETE
  • /_apis/graph/users/*#POST+DELETE
  • /*/_apis/graph/groups/*#POST+PATCH+DELETE
  • /*/_apis/graph/memberships/*/*#PUT+DELETE
  • /*/_apis/graph/scopes/*#POST+PATCH+DELETE
  • /*/_apis/graph/users/*#POST+DELETE
vso.graph_write
  • /_apis/graph/groups/*#POST+PATCH+DELETE
  • /_apis/graph/memberships/*/*#PUT+DELETE
  • /_apis/graph/scopes/*#POST+PATCH+DELETE
  • /_apis/graph/users/*#POST+DELETE
  • /*/_apis/graph/groups/*#POST+PATCH+DELETE
  • /*/_apis/graph/memberships/*/*#PUT+DELETE
  • /*/_apis/graph/scopes/*#POST+PATCH+DELETE
  • /*/_apis/graph/users/*#POST+DELETE
vso.security_manage
  • /Services/*/LocationService.asmx#POST
  • /*/Services/*/LocationService.asmx#POST
  • /DefaultCollection/*/Services/*/LocationService.asmx#POST
  • /*/Administration/*/LocationService.asmx#POST
  • /Services/*/Registration.asmx#POST
  • /*/Services/*/Registration.asmx#POST
  • /*/*/Administration/*/LocationService.asmx#POST
  • /_apis/SecurityNamespaces#POST
  • /_apis/AccessControlLists#POST+DELETE
  • /_apis/AccessControlEntries#POST+DELETE
  • /_apis/Permissions#DELETE
  • /DefaultCollection/_apis/SecurityNamespaces#POST
  • /DefaultCollection/_apis/AccessControlLists#POST+DELETE
  • /DefaultCollection/_apis/AccessControlEntries#POST+DELETE
  • /DefaultCollection/_apis/Permissions#DELETE
  • /Services/*/SecurityService.asmx#POST
  • /*/Services/*/SecurityService.asmx#POST
  • /Services/*/GroupSecurityService.asmx#POST
  • /*/Services/*/GroupSecurityService.asmx#POST
vso.memberEntitlementManagement
  • /_apis/MemberEntitlements/*#GET
  • /_apis/MemberEntitlements#GET
  • /DefaultCollection/_apis/MemberEntitlements/*#GET
  • /DefaultCollection/_apis/MemberEntitlements#GET
vso.memberEntitlementManagement_write
  • /_apis/MemberEntitlements/*#PATCH+DELETE
  • /_apis/MemberEntitlements#POST
  • /DefaultCollection/_apis/MemberEntitlements/*#PATCH+DELETE
  • /DefaultCollection/_apis/MemberEntitlements#POST
vso.workitemsearch
  • /_apis/search/workItemQueryResults#POST
  • /DefaultCollection/_apis/search/workItemQueryResults#POST
vso.wiki
  • /DefaultCollection/_apis/wiki/wikis#GET
  • /DefaultCollection/*/_apis/wiki/wikis#GET
vso.wiki_write
  • /DefaultCollection/_apis/wiki/wikis#GET+POST
  • /DefaultCollection/*/_apis/wiki/wikis#GET+POST
vso.codesearch
  • /_apis/search/codeQueryResults#POST
  • /DefaultCollection/_apis/search/codeQueryResults#POST
  • /_apis/search/codeAdvancedQueryResults#POST
  • /DefaultCollection/_apis/search/codeAdvancedQueryResults#POST

Friday, February 23, 2018

Uploading extensions to TFS

When creating a TFS extension, one ends up uploading it to the server all the time. Doing so through the Web UI is tedious, so here's a script for that.

It takes two parameters:

  • Server - the URL of the TFS instance, e. g. http://tfs.acme.com:8080/tfs/
  • File - the filename of the compiled .VSIX file, wildcards allowed
Since the file name of a compiled VSIX extension contains its version, the script takes wildcards in the File parameter. If there are multiple files that match the wildcard, the one with the latest modification date will be taken.

The script looks inside the VSIX to determine the publisher, the extension ID, and the version.

The script was meant for on-prem TFS. Microsoft's TFX command line tool can do the same for VSTS, but it doesn't support NTLM auth (because Node.js' HTTP client doesn't). Mine is in Powershell, where NTLM support comes out of the box.