Get all organizations in Azure DevOps using REST API - rest

I am trying to retrieve all the organizations in my account but in the documentation an organization is always required in the API call.
https://dev.azure.com/{organization}/_apis/...

If you load the current landing page, it displays all your organizations tied to your account. I assumed it had to get that information some way. I captured the network traffic and I believe you could get to the data you want using a system API call. However, it might change or might become unsupported without notice, so use at your own discretion.
You can get the information you want using this API:
Post https://dev.azure.com/{organization1}/_apis/Contribution/HierarchyQuery?api-version=5.0-preview.1
Body:
{
"contributionIds": ["ms.vss-features.my-organizations-data-provider"],
"dataProviderContext":
{
"properties":{}
}
}
Response:
{
"dataProviderSharedData": {},
"dataProviders": {
"ms.vss-web.component-data": {},
"ms.vss-web.shared-data": null,
"ms.vss-features.my-organizations-data-provider": {
"organizations": [
{
"id": "{redacted id}",
"name": "{organization1}",
"url": "https://{organization1}.visualstudio.com/"
},
{
"id": "{redacted id}",
"name": "{organization2}",
"url": "https://dev.azure.com/{organization2}/"
}
],
"createNewOrgUrl": "https://app.vsaex.visualstudio.com/go/signup?account=true"
}
} }

you can do it simply by making a call to get all the account you are member/ owner of. However for that you need your id, which can be easily fetched by making get profile call. Here are steps below:
Make a VSTS API call to get profile details using Bearer token or PAT
https://app.vssps.visualstudio.com/_apis/profile/profiles/me?api-version=5.1
This will return you, your Id:
{
"displayName": "xxxx",
"publicAlias": "xxx",
"emailAddress": "xxx",
"coreRevision": xxx,
"timeStamp": "2019-06-17T09:29:11.1917804+00:00",
"id": "{{We need this}}",
"revision": 298459751
}
Next, make a call to get all the accounts you are member of or owner of:
https://app.vssps.visualstudio.com/_apis/accounts?api-version=5.1&memberId={{Your Id}}
Response:
{
"count": 1,
"value": [
{
"accountId": "xxx",
"accountUri": "xxx",
"accountName": "xxx",
"properties": {}
}
]
}
It will return list of accounts you are associated with.

A REST API request/response pair can be separated into five components:
The request URI, in the following form:
VERB https://{instance}[/{team-project}]/_apis[/{area}]/{resource}?api-version={version}
instance:
The Azure DevOps Services organization or TFS server you're sending the request to.
They are structured as follows:
Azure DevOps Services: dev.azure.com/{organization}
The REST API's are organization specific. This is not documented at present. You could submit a feature request here: https://developercommunity.visualstudio.com/spaces/21/index.html
Our PM and product team will kindly review your suggestion. Sorry for any inconvenience.
As a workaround, you could use the API which captured from network traffic just as Matt mentioned.

We've been using "https://app.vssps.visualstudio.com/_apis/accounts" without specifying any API version and this returns all our accountnames
This is still working for us, but because of some other issues we have I'm adding the api version to all our api calls, however. For this I also run into the fact that https://learn.microsoft.com/en-us/rest/api/azure/devops/account/accounts/list?view=azure-devops-rest-5.0 requires an member or owner id.
Retrieving that needs an account/organization so it is a bit of a catch 22 situation.
For now I'll stay with just "https://app.vssps.visualstudio.com/_apis/accounts" I guess

I'm getting a sign-in response for both "app.vssps.visualstudio.com/_apis/accounts" and
Post https://dev.azure.com/{organization1}/_apis/Contribution/HierarchyQuery?api-version=5.0-preview.1
StatusCode : 203
StatusDescription : Non-Authoritative Information
EDIT:
Nevermind, it worked using the static MSA clientid and replyURL:
internal const string clientId = "872cd9fa-d31f-45e0-9eab-6e460a02d1f1"; //change to your app registration's Application ID, unless you are an MSA backed account
internal const string replyUri = "urn:ietf:wg:oauth:2.0:oob"; //change to your app registration's reply URI, unless you are an MSA backed account
//PromptBehavior.RefreshSession will enforce an authn prompt every time. NOTE: Auto will take your windows login state if possible
result = ctx.AcquireTokenAsync(azureDevOpsResourceId, clientId, new Uri(replyUri), promptBehavior).Result;
Console.WriteLine("Token expires on: " + result.ExpiresOn);
var bearerAuthHeader = new AuthenticationHeaderValue("Bearer", result.AccessToken);
// Headers
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("User-Agent", "ManagedClientConsoleAppSample");
client.DefaultRequestHeaders.Add("X-TFS-FedAuthRedirect", "Suppress");
client.DefaultRequestHeaders.Authorization = authHeader;
//Get Organizations
client.BaseAddress = new Uri("https://app.vssps.visualstudio.com/");
HttpResponseMessage response1 = client.GetAsync("_apis/accounts").Result;

Related

Turning the "Autocreate conversation" setting on via API

I'm attaching a picture here to make it more clear about what exactly I'm trying to do. I have sub-accounts under my account for which I purchase a number and that turn on "auto create conversation" setting for each of those subaccounts.
The way I do it from the Twilio Online GUI screeen is attached in the picture. However, I'd like to automate this using API. I haven't been able to do this exactly.
The closest thing I found was here. https://www.twilio.com/docs/conversations/api/address-configuration-resource
This hasn't worked for me.
Can someone suggest what I'm doing wrong?
Here are the steps I'm doing right now
Create a sub-account under main account
Purchase a number under sub-account
Attach the phone number to the default messaging service using the snippet below
await client.messaging.v1.services(service.sid)
.phoneNumbers
.create({
phoneNumberSid: activeNumberSid
});
Then create the addressConfiguration for this newly purchased number
as mentioned below
Address Configuration
client.conversations.v1.addressConfigurations
.create({
friendlyName: 'My Test Configuration',
'autoCreation.enabled': true,
'autoCreation.type': 'webhook',
'autoCreation.conversationServiceSid': 'ISXXXXXXXXXXXXXXXXXXXXXX',
'autoCreation.webhookUrl': 'https://example.com',
'autoCreation.webhookMethod': 'POST',
'autoCreation.webhookFilters': ['onParticipantAdded', 'onMessageAdded'],
type: 'sms',
address: '+37256123457'
})
.then(address_configuration => console.log(address_configuration.sid));
Here's the configuration of the default conversation service
I ran this code
async function _test() {
let service = await client.conversations.v1.services('IS4faafa8...').fetch();
console.log(JSON.stringify(service, null, 4));
}
to get this output (I have removed some characters from the ids for privacy reasons)
{
"accountSid": null,
"sid": "IS4faafa8.....",
"friendlyName": "Default Conversations Service",
"dateCreated": "2022-03-09T23:29:02.000Z",
"dateUpdated": "2022-07-20T17:49:19.000Z",
"url": "https://conversations.twilio.com/v1/Services/IS4faafa8.....",
"links": {
"users": "https://conversations.twilio.com/v1/Services/IS4faafa8...../Users",
"roles": "https://conversations.twilio.com/v1/Services/IS4faafa8...../Roles",
"participant_conversations": "https://conversations.twilio.com/v1/Services/IS4faafa8...../ParticipantConversations",
"conversations": "https://conversations.twilio.com/v1/Services/IS4faafa8...../Conversations",
"bindings": "https://conversations.twilio.com/v1/Services/IS4faafa8...../Bindings",
"configuration": "https://conversations.twilio.com/v1/Services/IS4faafa8...../Configuration"
}
}
Picture attached of the GUI Screen

How to get instagram username from new facebook graph API

Looking at the new Instagram Graph API - there is no direct way to retrieve username once a user is logged in. Although it says in the official document that a call like
"https://graph.facebook.com/v3.2/17841405822304914?fields=biography%2Cid%2Cusername%2Cwebsite&access_token=EAACwX..."
should return the following:
{
"biography": "Dino data crunching app",
"id": "17841405822304914",
"username": "metricsaurus",
"website": "http://www.metricsaurus.com/"
}
This currently returns an error, and looks like there is no such option to get only username of an instagram business user.
If you are talking about fetching username of an instagram business account which is linked to your facebook page, you can use the below curl
curl -i -X GET "https://graph.facebook.com/v3.2/me/accounts?fields=instagram_business_account%7Busername%2Cname%2Cig_id%7D&access_token=<access_token>"
Please replace access_token with your user access token in the above curl.
Sample reponse which you will get for the above curl is as below :
{
"data": [
{
"instagram_business_account": {
"username": "<instagram user name>",
"name": "<instagram display name>",
"id": "<corresponding facebook graph id for instagram profile>",
"ig_id": <instagram profile id>
},
"id": "<facebook page id>"
}
],
"paging": {
"cursors": {
"before": "MTc2Njg1MTU2MTI1ODA1",
"after": "OTg3MzU1NzExNDUwMDg3"
}
}
}
If it helps to someone.. Now its better to do it like this GrapAPI v10.0
FB.api('/' + pageID + '?fields=instagram_business_account{id,name,username}',
function (response) {
// TODO: whatever you want
},
{ access_token: accessToken }
);
EDIT: I wouldn't do it this way anymore. Its very old code, I would wrap it somehow and I am not sure this still works..
I was able to solve this only by using the old api.
According to their documentation, although the old API is about to become deprecated, as of now, it is meant for small businesses or personal apps.
The new Instagram Graph API is "An API for accessing data in large- and medium-sized Instagram Business Accounts"
Looks like FB doensn't know it's way around.

MS Graph REST API checkout user

I've managed to successfully checkout a file using the https://graph.microsoft.com/beta/drives/{driveId}/items/{itemId}/checkout
Now, I'd like to get the information about the user, who actually perform the checkout operation.
It's possible to check if the item is locked:
https://graph.microsoft.com/beta/drives/{driveId}/items/{itemId}?select=*,publication
However, according to DOCs, publication doesn't provide information about the checked user. Without information who locked the file is the whole checkin/checkout logic is useless.
This kind of information could be retrieved via the metadata for an item in a list as demonstrated below:
https://graph.microsoft.com/beta/sites/{site-id}/lists/{list-id}/items/{item-id}?expand=fields(select=CheckoutUserLookupId)
Once you get checkout user id (CheckoutUserLookupId field) , user details could be determined via the following endpoint:
https://graph.microsoft.com/v1.0/sites/{site-id}/lists('User Information List')/items/{CheckoutUserLookupId}
where CheckoutUserLookupId is the user id from the previous request
https://graph.microsoft.com/beta/sites/{site-id}/lists/{list-id}/items/{item-id} can't work with folders.
Anyway, drive endpoint "Allows access to the list as a drive" (according to MS Graph Docs). It works with folders as expected.
So I have
get the drive-id: /sites/${siteId}/drives
list root folder: /drives/{drive-id}/items/root/children?select=name,publication
if an item is locked, it's possible to list the activity on the item:
/drives/${idObj.driveId}/items/${idObj.fileId}?select=id&expand=activities
return list of actions:
"activities": [
{
"#odata.type": "#oneDrive.activityEntity",
"#odata.id": "https://xxxxxxxxxx/v2.0/oneDrive.activityEntity2a3649d6-2xxxxx",
"#odata.editLink": "oneDrive.activityEntity2a3649d6xxxxxx",
"#sharePoint.localizedRelativeTime": "0|July 30",
"action": {
"checkout": {}
},
"actor": {
"user": {
"email": "XXX#XXX",
"displayName": "vladimir",
"self": {},
"userPrincipalName": "XXX#XXX
}
},
"id": "XXXXXXXXXXXXXX",
"times": {
"recordedTime": "2018-07-31T04:59:03Z"
}
},
although no user ID at least a have the email....

When `actions.intent.TRANSACTION_REQUIREMENTS_CHECK` returns result different than `OK`?

I want to create a chatbot with Dialogflow and Google Assistant along with Google Transactions API for enabling a user to order a chocolate box. For now my agent contains the following four intents:
Default Welcome Intent (text response: Hello, do you want to buy a chocolate box?)
Default Fallback Intent
Int1 (training phrase: Yes, I want, fulfilment: enabled webhook call)
Int2 (event: actions_intent_TRANSACTION_REQUIREMENTS_CHECK )
I am using Dialogflow Json instead of Node.js to connect my agent with Transactions API. I want to test that the user meets the transaction requirements (when ordering the chocolate box) by using the actions.intent.TRANSACTION_REQUIREMENTS_CHECK action of Google actions. For this reason, following Google docs, when Int1 is triggered I am using a webhook which connects Google Assistant to the following python script (back-end):
from flask import Flask, render_template, request, jsonify
from flask_cors import CORS
import requests
app = Flask(__name__)
CORS(app)
#app.route("/", methods=['POST'])
def index():
data = request.get_json()
intent = data["queryResult"]["intent"]["displayName"]
if (intent == 'Int1'):
return jsonify({ "data": {
"google": {
"expectUserResponse": True,
"isSsml": False,
"noInputPrompts": [],
"systemIntent": {
"data": {
"#type": "type.googleapis.com/google.actions.v2.TransactionRequirementsCheckSpec",
"paymentOptions": {
"actionProvidedOptions": {
"displayName": "VISA-1234",
"paymentType": "PAYMENT_CARD"
}
}
},
"intent": "actions.intent.TRANSACTION_REQUIREMENTS_CHECK"
}
}
}
})
else:
return jsonify({'message': 'HERE'})
if __name__== "__main__":
app.run(debug=True)
The result in the json response which I receive after actions.intent.TRANSACTION_REQUIREMENTS_CHECK and Int2 are triggered is:
"arguments": [
{
"extension": {
"#type": "type.googleapis.com/google.actions.v2.TransactionRequirementsCheckResult",
"resultType": "OK"
},
"name": "TRANSACTION_REQUIREMENTS_CHECK_RESULT"
}
]
The confusing fact is that even if I send:
{
"displayName": "FALSE",
"paymentType": "PAYMENT_CARD"
}
the response is the same which means that it returns again OK.
When I send something like this
{
"displayName": "FALSE",
"paymentType": "WRONG"
}
then I get an error:
API Version 2: Failed to parse JSON response string with 'INVALID_ARGUMENT' error: "(payment_options.action_provided_options.payment_type): invalid value "WRONG" for type TYPE_ENUM".
but this is not exactly given by actions.intent.TRANSACTION_REQUIREMENTS_CHECK and Int2 because these two are not triggered so I do not get any json response back with a result different than OK.
Therefore, my question is: In which cases am I going to receive a result from actions.intent.TRANSACTION_REQUIREMENTS_CHECK which is different than OK?
If I am going to get an OK result for anything that I am writing then what is the point of using actions.intent.TRANSACTION_REQUIREMENTS_CHECK?
P.S.
I have in mind the following about actions.intent.TRANSACTION_REQUIREMENTS_CHECK from Google docs:
Note: The actions.intent.TRANSACTION_REQUIREMENTS_CHECK intent is
currently under development and will return a success state regardless
of the user's payment settings and locale. To test out the failure
state scenario, request the intent on a voice-activated speaker.
but still I am not seeing any difference when I using this app on Google Assistant with my voice on my mobile phone.
I think that you we have to return to Google docs to solve this. According to Google docs the possible responses of actions.intent.TRANSACTION_REQUIREMENTS_CHECK are the following: RESULT_TYPE_UNSPECIFIED, OK, USER_ACTION_REQUIRED, ASSISTANT_SURFACE_NOT_SUPPORTED, REGION_NOT_SUPPORTED
(image).
Nothing of them has to do exactly with this:
"paymentOptions": {
"actionProvidedOptions": {
"displayName": "VISA-1234",
"paymentType": "PAYMENT_CARD"
}
}
This is also because your back-end cannot (or it is not even allowed to) directly reach the payment details of the user so the json above is only inserted by your back-end if you know them or in a sense you can write whatever you want. This is only for being displayed at the order preview and it is not cross-checked with the payment details of the user's Google account.
In conclusion, actions.intent.TRANSACTION_REQUIREMENTS_CHECK may only return a non OK status if the result is unspecified (RESULT_TYPE_UNSPECIFIED) or if the user is expected to take action (USER_ACTION_REQUIRED) or if the transactions are not supported on current device/surface (ASSISTANT_SURFACE_NOT_SUPPORTED) or if the transactions are not supported for current region/country (REGION_NOT_SUPPORTED).

API method to escalate ticket to SoftLayer

Using BAP creds I am able to pull all my accounts tickets, check content and update. Which API call to use to escalate ticket to SoftLayer?
this is the API service that BAP uses to perform its actions:
http://sldn.softlayer.com/reference/services/SoftLayer_Brand
as you can see there is a method to list the tickets, however there is no a method to create tickets, that is because when you create a ticket using BAP is the same thing like if you would create the ticket using control portal the method used is this:
http://sldn.softlayer.com/reference/services/SoftLayer_Ticket/createStandardTicket
here an example to create tickets using the Softlayer's Python client:
https://softlayer.github.io/python/create_ticket/
using REST:
POST https://$USERNAME:$APIKEY#api.softlayer.com/rest/v3/SoftLayer_Ticket/createStandardTicket
payload:
{
"parameters":[{
"subjectId": 1121,
"assignedUserId": 11111
},"this is my test ticket"]
}
Note: replace assignedUserId with a valid user id
Regards
To escalate a ticket to SoftLayer, you need to follow these steps:
1. Add an update to the ticket
https://$user:$apiKey#api.softlayer.com/rest/v3/SoftLayer_Ticket/21588750/addUpdate
Method: Post
{
"parameters":[
{
"entry":"Escalate to SoftLayer",
"type":
{
"keyName":"AGENT"
}
}
]
}
2. Edit the ticket with the following information:
https://$user:$apiKey#api.softlayer.com/rest/v3/SoftLayer_Ticket/21588750/edit
Method: Post
{
"parameters":[
{
"groupId":1008, "changeOwnerFlag":true
}
]
}
Note: “groupId : 1008” refers to Support group. To get available group identifiers (groupId), try the following rest request:
https://$user:$apiKey#api.softlayer.com/rest/v3/SoftLayer_Ticket/getAllTicketGroups
Method: Get
References:
SoftLayer_Ticket::addUpdate
SoftLayer_Ticket::edit
SoftLayer_Ticket::getAllTicketGroups