On a site I'm developing I embed videos from YouTube and want to get the video title and its description.
How do I get that information?
You can do it with oembed.
Example:
http://www.youtube.com/oembed?url=http%3A//youtube.com/watch%3Fv%3DM3r2XDceM6A&format=json
Youtube API V2.0 has been deprecated. It shows some wrong value for title "youtube.com/devicesupport" . pLease switch on to API V3.0
YOu can refer the following PHP code and modify yours in js or jquery as per your needs..
function youtube_title($id) {
$id = 'YOUTUBE_ID';
// returns a single line of JSON that contains the video title. Not a giant request.
$videoTitle = file_get_contents("https://www.googleapis.com/youtube/v3/videos?id=".$id."&key=YOUR_API_KEY&fields=items(id,snippet(title),statistics)&part=snippet,statistics");
// despite # suppress, it will be false if it fails
if ($videoTitle) {
$json = json_decode($videoTitle, true);
return $json['items'][0]['snippet']['title'];
} else {
return false;
}
}
update:
Jquery code to get the title-
$.getJSON('https://www.googleapis.com/youtube/v3/videos?id={VIDEOID}&key={YOUR API KEY}&part=snippet&callback=?',function(data){
if (typeof(data.items[0]) != "undefined") {
console.log('video exists ' + data.items[0].snippet.title);
} else {
console.log('video not exists');
}
});
To get the DESCRIPTION element, you need to access the gdata version of the video's info, and you can return json using alt=json on the path. In this case, oHg5SJYRHA0 is the video ID, found at the end of the url of the video you're working with on YouTube, e.g.
www.youtube.com/watch?v=oHg5SJYRHA0
http://gdata.youtube.com/feeds/api/videos/oHg5SJYRHA0?v=2&alt=json&prettyprint=true
(the prettyprint is formatting to make that easy to read, you don't need it for what you're doing)
You can grab the JSON, add it into a variable and access it using jQuery:
var youTubeURL = 'http://gdata.youtube.com/feeds/api/videos/oHg5SJYRHA0?v=2&alt=json';
var json = (function() {
var json = null;
$.ajax({
'async': false,
'global': false,
'url': youTubeURL,
'dataType': "json",
'success': function(data) {
json = data;
}
});
return json;
})();
Then access it using object notation:
alert("Title: " + json.entry.title.$t +"\nDescription:\n " + json.entry.media$group.media$description.$t + "\n");
gdata is no longer available
you can use the following instead
https://www.googleapis.com/youtube/v3/videos?part=snippet&id=(Video_ID)&key=(API_Key)
I read this topic a bit in delay.
I did something like this using jSON and YT API's
$json = json_decode( file_get_contents("http://gdata.youtube.com/feeds/api/videos/".$rs['vid']."?v=2&prettyprint=true&alt=jsonc") );
Note: $rs['vid'] is the video ID dinamically retrived from my DB.
Once you put the contents in the handle $json you can retrive like this:
$json->data->description;
$json->data->title;
use var_dump( $json ) to view all values you can access.
I'd start by taking a look at Youtube Data API to get what you want: http://code.google.com/apis/youtube/getting_started.html#data_api
GData is deprecated, but one can still get the video description by calling this endpoint:
https://www.googleapis.com/youtube/v3/videos?part=snippet&id=[video_id]&key=[api_key]
It will return a response of the form:
{
"kind": "youtube#videoListResponse",
"etag": "\"...\"",
"pageInfo": {
"totalResults": 1,
"resultsPerPage": 1
},
"items": [
{
"kind": "youtube#video",
"etag": "\"...\"",
"id": "...",
"snippet": {
"publishedAt": "...",
"channelId": "...",
"title": "...",
"description": "...",
"thumbnails": { ... },
"channelTitle": "...",
"tags": [ ... ],
"categoryId": "...",
"liveBroadcastContent": "...",
"localized": {
"title": "...",
"description": "..."
},
"defaultAudioLanguage": "..."
}
}
]
}
The description can be found at items.localized.description.
Related
I started exploring Google Docs API in Python. It does pretty much everything I want it to do except for one thing.
I can replace the text of a document but I can't change the value of the hyperlinks.
Meaning if a link looks like this : a link, I can change the value of the text a link but not the target URL.
I've been going through the documentation but I can't find anything about it. Could it be a missing feature or am I missing the way to do that?
You can modify the hyperlink using UpdateTextStyleRequest of the batchupdate method in Google Docs API. At this time, please set the property of Link of TextStyle.
Endpoint
POST https://docs.googleapis.com/v1/documents/{file ID}:batchUpdate
Request body:
{
"requests": [
{
"updateTextStyle": {
"textStyle": {
"link": {
"url": "https://sampleUrl" # Please set the modified URL here.
}
},
"range": {
"startIndex": 1,
"endIndex": 2
},
"fields": "link"
}
}
]
}
Note:
From your question, I could understand that you have already used Google Docs API and you can modify the text of the link text. I think that you can modify the link using above request body and the script you have.
References:
UpdateTextStyleRequest
TextStyle
Link
If this was not useful for your situation, I apologize.
Edit:
You want to retrieve the text with the hyperlink.
From your reply comment, I could understand like above. When my understanding is correct, you can retrieve it using documents.get method. In this case, when fields is used, the response become to easily read.
Endpoint:
GET https://docs.googleapis.com/v1/documents/{file ID}?fields=body(content(paragraph(elements(endIndex%2CstartIndex%2CtextRun(content%2CtextStyle%2Flink%2Furl)))))
In this endpoint, body(content(paragraph(elements(endIndex,startIndex,textRun(content,textStyle/link/url))))) is used as fields.
Sample response:
For example, when the following texts are put in a Google Document and def has a hyperlink,
abc
def
The response is as follows. From the following result, you can retrieve the position of text with the hyperlink can be retrieved. Using this, you can modify the hyperlink.
{
"body": {
"content": [
{},
{
"paragraph": {
"elements": [
{
"startIndex": 1,
"endIndex": 5,
"textRun": {
"content": "abc\n",
"textStyle": {}
}
}
]
}
},
{
"paragraph": {
"elements": [
{
"startIndex": 5,
"endIndex": 8,
"textRun": {
"content": "def",
"textStyle": {
"link": {
"url": "https://sample/"
}
}
}
},
{
"startIndex": 8,
"endIndex": 9,
"textRun": {
"content": "\n",
"textStyle": {}
}
}
]
}
}
]
}
}
Reference:
documents.get
batchUpdate requires to know position of text, we can get document with all content and find positions of links
In my case I implement it as:
Copy template to new place with final name
Replace link texts and other parts of text
Get document
Find links positions in doc
Update link URLs
Here example in nodejs
const {google, docs_v1} = require('googleapis');
async function replaceInDoc(doc) {
let documentId = 'some doc id'
let auth = 'auth value for user'
let linkNewUrl = 'https://github.com/googleapis/google-api-nodejs-client'
google.options({auth: auth})
var docs = new docs_v1.Docs({}, google)
// document should have link with http://repo-url.com text, we will update it
var requests = [
{
replaceAllText: {
containsText: {
text: 'http://repo-url.com',
matchCase: true,
},
replaceText: linkNewUrl,
},
}
]
var updateRes = await docs.documents.batchUpdate({
documentId: documentId,
resource: {
requests: requests,
},
});
var docInfo = await docs.documents.get({documentId: documentId})
var linkPos = findLinksInDoc(docInfo)
// set new url to link by position of link in the document
var requests = [
{
updateTextStyle: {
textStyle: {
link: {
url: linkNewUrl
}
},
range: {
startIndex: linkPos[linkNewUrl][0],
endIndex: linkPos[linkNewUrl][1]
},
fields: "link"
}
}
]
var updateRes = await docs.documents.batchUpdate({
documentId: documentId,
resource: {
requests: requests,
},
});
}
// returns hash as { 'http://example.com': [startPosition, endPosition] }
function findLinksInDoc(doc) {
var links = {}
doc.data.body.content.forEach(section => {
if (section.paragraph) {
section.paragraph.elements.forEach(element => {
if (element.textRun && element.textRun.textStyle.link) {
links[element.textRun.content] = [element.startIndex, element.endIndex]
}
})
}
})
return links
}
I have the code setup for the Youtube API with oauth login. Login appears to work properly. I can even see the requests hitting my analytics. However, when I run the code to unsubscribe from a channel, it never works on any channel ID I give it. It should be noted that I'm using the exact example from googles dev docs(see "full sample" option for javascript)... I'm guessing the code is correct and this is some other auth/lookup problem.
API code:
alert("deleting steven!!!!!!");
buildApiRequest('DELETE',
'/youtube/v3/subscriptions',
{'id': 'UCMtFAi84ehTSYSE9XoHefig'});
Stock Youtube API Code:
function executeRequest(request) {
request.execute(function(response) {
console.log(response);
});
}
function buildApiRequest(requestMethod, path, params, properties) {
params = removeEmptyParams(params);
var request;
if (properties) {
var resource = createResource(properties);
request = gapi.client.request({
'body': resource,
'method': requestMethod,
'path': path,
'params': params
});
} else {
request = gapi.client.request({
'method': requestMethod,
'path': path,
'params': params
});
}
executeRequest(request);
}
Here is the error:
{
"error": {
"errors": [
{
"domain": "youtube.subscription",
"reason": "subscriptionNotFound",
"message": "The subscription that you are trying to delete cannot be found. Check the value of the requests \u003ccode\u003eid\u003c/code\u003e parameter to ensure that it is correct."
}
],
"code": 404,
"message": "The subscription that you are trying to delete cannot be found. Check the value of the requests \u003ccode\u003eid\u003c/code\u003e parameter to ensure that it is correct."
}
}
Remember that the ID you have to send is not the channel ID. It's the ID of the subscriptions.
You can get it by sending request to check your subscriptions with the channel. For example
Request:
buildApiRequest('GET',
'/youtube/v3/subscriptions',
{'forChannelId': 'UCEhZglE9MQ4zTL5ErNXt5mg',
'mine': 'true',
'part': 'snippet,contentDetails'});
Response:
{
"kind": "youtube#subscription",
"etag": "\"XI7nbFXulYBIpL0ayR_gDh3eu1k/KrR9MNb4Xs1eNjWMxAH-f5ccsos\"",
"id": "Xmg72z6q83hK2hjx0J4ZwNVcgGz8fu9JCjeHu6eIb3M",
"snippet": {
"publishedAt": "2018-09-30T16:51:47.000Z",
"title": "Rebeca Willett",
"description": "",
"resourceId": {
"kind": "youtube#channel",
"channelId": "UCEhZglE9MQ4zTL5ErNXt5mg"
},
"channelId": "UCWfZYaoFrUOSoHNhCOOqKCQ",
"thumbnails": {
...
}
Using ID in the response to send request for unsubscribing:
buildApiRequest('DELETE',
'/youtube/v3/subscriptions',
{'id': 'Xmg72z6q83hK2hjx0J4ZwNVcgGz8fu9JCjeHu6eIb3M'});
Here is the google docs for getting subscriptions ID
I'm currently developing a solution which is retrieving e-mails via the Microsoft Graph API. In november 2015 Microsoft stated it is ready for production and I've read in another forum post that if you start now on developing using a Microsoft API, you should use the Graph API, since it is the future.
Everything is going well except for one thing and that is the following.
I must retrieve e-mails. Inside these e-mails there are of course attachments. These attachments come in some variaties. fileAttachment (images, documents etc.), referenceAttachments and itemAttachments (outlook-item). The issue here is with the itemAttachments. An itemAttachment can be anything from an appointment to another message. The problem here is that I'm not able to get and retrieve the contentBytes in some way which is working for fileAttachments. A related object to itemAttachment is outlookItem. There is also a page with a description made for this outlookItem, but the examples and the details are missing.
The user rights are set to Mail.Read and Mail.ReadWrite.
Links:
General overview: http://graph.microsoft.io/docs/overview/overview
Get outlookItem (empty?):
Example call and response I get. Please note the types of the attachments.
https://graph.microsoft.com/v1.0 /users/ /messages/ /attachments
{
"#odata.context": "link",
"value": [
{
"#odata.type": "#microsoft.graph.fileAttachment",
"id": "AAMkAGU2NmIwMTcxLTljYzUtNGRiMi1hZjczLTllNzhiZDRiNWZlZABGAAAAPAD_Lx_gimDGRqSr98J_O_e6BwDcWyYHlO7rS5_XpLHCx6NSAAIMC0V-AADcWyYHlO7rS5_XpLHCx6NSAAIMC6RgAAABEgAQAGhN_vm1RlBPt7V4N9a89UY=",
"lastModifiedDateTime": "2016-01-13T14:25:33Z",
"name": "image001.png",
"contentType": "image/png",
"size": 5077,
"isInline": true,
"contentId": "image001.png#01D14E16.A3A32480",
"contentLocation": null,
"contentBytes": "iVBORw0KGgoAAAANSUhEUgAAAKAAAACCCAIAAABOyVRHAAAAAXNSR0IArs4c6QAAEndJREFUeF7tXQ1QFFe2bkbU... (truncated)"
},
{
"#odata.type": "#microsoft.graph.fileAttachment",
"id": "AAMkAGU2NmIwMTcxLTljYzUtNGRiMi1hZjczLTllNzhiZDRiNWZlZABGAAAAPAD_Lx_gimDGRqSr98J_O_e6BwDcWyYHlO7rS5_XpLHCx6NSAAIMC0V-AADcWyYHlO7rS5_XpLHCx6NSAAIMC6RgAAABEgAQAFnSLgIC5wZOosmLtBWK8gE=",
"lastModifiedDateTime": "2016-01-13T14:25:34Z",
"name": "image002.png",
"contentType": "image/png",
"size": 3722,
"isInline": true,
"contentId": "image002.png#01D14E16.A3A32480",
"contentLocation": null,
"contentBytes": "iVBORw0KGgoAAAANSUhEUgAAAPoAAABSCAYAAAB9o8m+AAAAGXRFWHRTb... (truncated)"
},
{
"#odata.type": "#microsoft.graph.fileAttachment",
"id": "AAMkAGU2NmIwMTcxLTljYzUtNGRiMi1hZjczLTllNzhiZDRiNWZlZABGAAAAPAD_Lx_gimDGRqSr98J_O_e6BwDcWyYHlO7rS5_XpLHCx6NSAAIMC0V-AADcWyYHlO7rS5_XpLHCx6NSAAIMC6RgAAABEgAQANOuw7m8sW1Ot3MivYQ5OYU=",
"lastModifiedDateTime": "2016-01-13T14:25:24Z",
"name": "Knipsel.PNG",
"contentType": null,
"size": 7641,
"isInline": false,
"contentId": null,
"contentLocation": null,
"contentBytes": "iVBORw0KGgoAAAANSUhEUgAAAKAAAACCCAYAAADBq8MQAAA... (truncated)"
},
{
"#odata.type": "#microsoft.graph.itemAttachment",
"id": "AAMkAGU2NmIwMTcxLTljYzUtNGRiMi1hZjczLTllNzhiZDRiNWZlZABGAAAAPAD_Lx_gimDGRqSr98J_O_e6BwDcWyYHlO7rS5_XpLHCx6NSAAIMC0V-AADcWyYHlO7rS5_XpLHCx6NSAAIMC6RgAAABEgAQAPEUC740tjtAlNTe8NpopUI=",
"lastModifiedDateTime": "2016-01-14T15:55:07Z",
"name": "RE: Test met plaatje",
"contentType": null,
"size": 36972,
"isInline": false
}
]
}
I've tried to change the GET-statement by pasting the attachment id with or without the messages path and the expand feature (which is only supported one level deep), but I can't seem te find the solution.
Something I've found is this question, which is kind of the same, however it is for the office365 unified API. How to retrieve ItemAttachment contents from Office 365 REST API?.
So, the question: How can I retrieve the contents of an outlookItem via the Microsoft Graph API? And how do I know what to expect? Can anybody help me getting past this obstacle.
Use $expand option:
GET https://graph.microsoft.com/v1.0/me/messages('AAMkADA1M-zAAA=')/attachments('AAMkADA1M-CJKtzmnlcqVgqI=')/?$expand=microsoft.graph.itemattachment/item
Response:
HTTP/1.1 200 OK
Content-type: application/json
{
"#odata.context":"https://graph.microsoft.com/v1.0/$metadata#users('d1a2fae9-db66-4cc9-8133-2184c77af1b8')/messages('AAMkADA1M-zAAA%3D')/attachments/$entity",
"#odata.type":"#microsoft.graph.itemAttachment",
"id":"AAMkADA1MCJKtzmnlcqVgqI=",
"lastModifiedDateTime":"2017-07-21T00:20:34Z",
"name":"Reminder - please bring laptop",
"contentType":null,
"size":32005,
"isInline":false,
"item#odata.context":"https://graph.microsoft.com/v1.0/$metadata#users('d1a2fae9-db66-4cc9-8133-2184c77af1b8')/messages('AAMkADA1M-zAAA%3D')/attachments('AAMkADA1M-CJKtzmnlcqVgqI%3D')/microsoft.graph.itemAttachment/item/$entity",
"item":{
"#odata.type":"#microsoft.graph.message",
"id":"",
"createdDateTime":"2017-07-21T00:20:41Z",
"lastModifiedDateTime":"2017-07-21T00:20:34Z",
"receivedDateTime":"2017-07-21T00:19:55Z",
"sentDateTime":"2017-07-21T00:19:52Z",
"hasAttachments":false,
"internetMessageId":"<BY2PR15MB05189A084C01F466709E414F9CA40#BY2PR15MB0518.namprd15.prod.outlook.com>",
"subject":"Reminder - please bring laptop",
"importance":"normal",
"conversationId":"AAQkADA1MzMyOGI4LTlkZDctNDkzYy05M2RiLTdiN2E1NDE3MTRkOQAQAMG_NSCMBqdKrLa2EmR-lO0=",
"isDeliveryReceiptRequested":false,
"isReadReceiptRequested":false,
"isRead":false,
"isDraft":false,
"webLink":"https://outlook.office365.com/owa/?ItemID=AAMkADA1M3MTRkOQAAAA%3D%3D&exvsurl=1&viewmodel=ReadMessageItem",
"body":{
"contentType":"html",
"content":"<html><head>\r\n</head>\r\n<body>\r\n</body>\r\n</html>"
},
"sender":{
"emailAddress":{
"name":"Adele Vance",
"address":"AdeleV#contoso.onmicrosoft.com"
}
},
"from":{
"emailAddress":{
"name":"Adele Vance",
"address":"AdeleV#contoso.onmicrosoft.com"
}
},
"toRecipients":[
{
"emailAddress":{
"name":"Alex Wilbur",
"address":"AlexW#contoso.onmicrosoft.com"
}
}
],
"ccRecipients":[
{
"emailAddress":{
"name":"Adele Vance",
"address":"AdeleV#contoso.onmicrosoft.com"
}
}
]
}
}
Source: https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/attachment_get#request-2
The official documentation: https://graph.microsoft.io/en-us/docs/api-reference/beta/api/attachment_get.htm . Use valid Bearer authentication access code, and check for appropriate Graph API permissions on the Azure management portal. Attachment is based64 encoded string, coming in the contentBytes field. Correct Uri for loading list of a message attachments is: https://graph.microsoft.com/beta/me/messages/[ message Id ]/attachments. Sample code to call attachments endpoint is below:
using (var client = new HttpClient())
{
using (var request = new HttpRequestMessage(HttpMethod.Get,
"https://graph.microsoft.com/beta/me/messages/..id../attachments"))
{
request.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", "...valid access token...");
using (HttpResponseMessage response = await client.SendAsync(request))
{
if (response.StatusCode == HttpStatusCode.OK)
{
result = await response.Content.ReadAsStringAsync();
var json = JObject.Parse(result);
}
}
}
}
Get attachment using MS Graph API for Java:
First build the graph client. Sample code
ClientSecretCredential clientSecretCredential = new ClientSecretCredentialBuilder()
.clientId(yourClientId).clientSecret(yourClientSecret)
.tenantId(yourTenantId).build();
TokenCredentialAuthProvider tokenCredAuthProvider = new TokenCredentialAuthProvider(clientSecretCredential);
GraphServiceClient<Request> gClient = GraphServiceClient.builder().authenticationProvider(tokenCredAuthProvider)
.buildClient();
Either get all the attachments for a message-
FileAttachment fa = (FileAttachment) graphClient.users(id).messages(messageId).attachments().buildRequest().get();
Or get a particular attachment by passing the attachment id:
FileAttachment fa = (FileAttachment) graphClient.users(id).messages(messageId).attachments(attachmentId).buildRequest().get();
//Copy file attachment into a File from byte stream using FileUtils.
FileUtils.writeByteArrayToFile(new File(yourFileLocation), fa.contentBytes);
You can also similarly either get all users, messages or attachments or pass particular id to get a unique result for these entities.
When performing a search request to the API, the height & width fields of the thumbnails are not included in the response, even when specified in the fields parameter. Here's an example for a JS object that provides the API parameters:
{
part: 'snippet',
type: 'video',
order: 'relevance',
q: 'test',
fields: 'items(snippet(thumbnails(high(url,height,width))))'
}
Which translates into the following request URL:
https://www.googleapis.com/youtube/v3/search?order=relevance&part=snippet&q=test&fields=items(snippet(thumbnails(high(url%2Cheight%2Cwidth))))&type=video&key={YOUR_API_KEY}
This call yields the following response without the width or height of the thumbnails.
{
"items": [
{
"snippet": {
"thumbnails": {
"high": {
"url": "https://i.ytimg.com/vi/3HKs8WTGzw8/hqdefault.jpg"
}
}
}
},
{
"snippet": {
"thumbnails": {
"high": {
"url": "https://i.ytimg.com/vi/vW_8K_mLtsU/hqdefault.jpg"
}
}
}
},
{
"snippet": {
"thumbnails": {
"high": {
"url": "https://i.ytimg.com/vi/4Yk-jd4BHys/hqdefault.jpg"
}
}
}
},
{
"snippet": {
"thumbnails": {
"high": {
"url": "https://i.ytimg.com/vi/HU9mnag7vSM/hqdefault.jpg"
}
}
}
},
{
"snippet": {
"thumbnails": {
"high": {
"url": "https://i.ytimg.com/vi/pyrH7b0zHwU/hqdefault.jpg"
}
}
}
}
]
}
This similarly does not work for the default or medium thumbnail keys either.
How can these fields be retrieved?
The search endpoint won't return those details. You'll have to take the IDs returned from the search and do another API call to the videos endpoint for the snippet. For instance
https://www.googleapis.com/youtube/v3/videos?part=snippet&id={VIDEO_ID}&key={YOUR_API_KEY}
As per Youtube Date API (v3) Search Method returns as per document but its not working properly.
Now you should try alternative method by the API call of Video.
URL :- https://www.googleapis.com/youtube/v3/videos?part=snippet&id={VIDEO_ID}&key={YOUR_API_KEY}
VIDEO_ID = Return by Search API
YOUR_API_KEY = Google Project API key
Try it
$.get(
"https://www.googleapis.com/youtube/v3/search",{
order:'relevance',
part : 'snippet',
type : 'video',
q: 'test',
key: 'XXXXXXX'},
function(data) {
alert(data.items.length);
$.each( data.items, function( i, item ) {
pid = item.id.videoId;
getVids(pid);
});
}
);
//Get Videos
function getVids(pid){
$.get(
"https://www.googleapis.com/youtube/v3/videos",{
part : 'snippet',
id : pid,
key: 'XXXXXXXX'},
function(data) {
//Code whatever you want
}
);
}
I have to update multiple invideo promotion details for a particular channel.
My request is as follows:
var requestOptions={
part: 'invideoPromotion',
onBehalfOfContentOwner: 'contentOwner',
resource:{
id: channelId,
invideoPromotion: {
"defaultTiming": {
"offsetMs": 2000,
"type": "offsetFromStart"
},
"items": [
{
"promotedByContentOwner": true,
"timing":
{
"offsetMs":4000,
"duration" : 5000,
"type":"offsetFromStart"
},
"id":{
"videoId": videoid1,
"type": "video"
}
},
{
"promotedByContentOwner": true,
"timing":
{
"offsetMs":11000,
"duration" : 5000,
"type":"offsetFromStart"
},
"id":{
"videoId": videoId2,
"type": "video"
}
}
],
"position": {
"type": "corner",
"cornerPosition": "topLeft"
}
}
}
};
console.log(requestOptions);
var request = gapi.client.youtube.channels.update(requestOptions);
request.execute(function (response) {});
But when i try to execute this, I am getting error
0: {error:{code:500}, id:gapiRpc}
error: {code:500}
code: 500
id: "gapiRpc"
Even When I try to do this using the youtube api explorer
https://developers.google.com/apis-explorer/#p/youtube/v3/youtube.channels.update ,
I am getting Internal server Error.
Can somebody let me know where I am going wrong.
You cannot promote more than one video. I also tried the same but getting an error "exceeded the number of promoted items". So you can only promote one video at a time.