YouTube Analytics API - Content owner reports - youtube-api

So, I am trying to use Monetary Analytics API, to fetch earnings report for given YouTube channel.
https://developers.google.com/youtube/analytics/v1/content_owner_reports
However, to use this API, the following is required:
To retrieve a content owner report, set the ids parameter value in
your API request to contentOwner==OWNER_NAME, where OWNER_NAME
specifies the content owner's ID. Ask your partner manager if you are
unsure of the value.
So, after browsing online, I've found unofficial documentation, that may be what I'm looking for.
http://jump.techden.in/developers.google.com/youtube/partner/docs/v1/contentOwners/list
So I added https://www.googleapis.com/auth/youtubepartner scope, reauthenticated, and made this request:
def list_content_owners
conn = FaradayAdapter.new("https://www.googleapis.com").conn
params = {
:fetchMine => true,
:key => DEVELOPER_KEY
}
resp = conn.get do |req|
req.url "/youtube/partner/v1/contentOwners", params
req.headers["Authorization"] = "Bearer #{#token}"
end
debugger
return nil unless resp.try(:status) == 200
JSON.parse resp.body || nil
end
However, I get the following 403 error:
(rdb:1) resp.body "{\n \"error\": {\n \"errors\": [\n {\n
\"domain\": \"usageLimits\",\n \"reason\":
\"accessNotConfigured\",\n \"message\": \"Access Not Configured\"\n
}\n ],\n \"code\": 403,\n \"message\": \"Access Not Configured\"\n
}\n}\n"
I've looked into my developer console https://code.google.com/apis/console/ and I already have all YouTube related API's enabled. There is no special partner API listing available.
So, if I can't get contentOwner id, whats the point of Analytics API?

As clearly described in the page you were referring to : https://developers.google.com/youtube/analytics/v1/content_owner_reports
contentOwner is related to Content ID API and and only available to few partners. Make sure you have this API available in your console or ask your partner manager if you are eligible for this API.

Related

What auth flow to use with spa and service account msal

There's so many different flows in the Microsoft docs that I have no clue what one is needed for me. I am using React and Python. (I understand node, so if someone explains using node/express its fine)
What user should see:
A page with a button to login, nav is there but wont work till logged in. The login creates a popup to sign in with Microsoft account. Once signed in, the user will be able to use nav to see dynamics information.
What I am trying to do:
This app needs to sign in a user and obtain the users email through 'https://graph.microsoft.com/v1.0/me'.(no client secrets needed) Then I need to send that email in this request;
(The tenant == {company}.crm.dynamics.com.)
allInfo = requests.get(
f'https://{TENANT}api/data/v9.0/company_partneruserses?$filter=company_email eq \'{email}\'', headers=headers).json()
This backend request needs to have a client secret to obtain the information. So I believe my backend also needs to be logged on to a service account. I believe I need to get a token for my backend to make requests on behalf of the service account.
What I have:
I have a React frontend that is signing a user in and calling 'https://graph.microsoft.com/v1.0/me' correctly and getting that email. Once I get the email, I am sending it to my backend.
Now I have no clue how to proceed and have tried many things.
What I have tried for backend:
Attempt 1: I get a token but error: {'error': {'code': '0x80072560', 'message': 'The user is not a member of the organization.'}}. Problem is, this id is the Azure AD ID. It should def work
#app.route('/dynToken', methods=['POST'])
def get_dyn_token():
req = request.get_json()
partnerEmail = req['partnerEmail']
token = req['accessToken']
body = {
"client_id": microsoft_client_id,
"client_secret": client_secret,
"grant_type": "client_credentials",
"scope": SCOPE_DYN,
}
TENANTID = '{hash here}'
res = requests.post(
f'https://login.microsoftonline.com/{TENANTID}/oauth2/v2.0/token', data=body).json()
dyn_token = res['access_token']
headers = {
"Prefer": "odata.include-annotations=\"*\"",
"content-type": "application/json; odata.metadata=full",
"Authorization": f"Bearer {dyn_token}"
}
try:
allInfo = requests.get(
f'https://{TENANT}api/data/v9.0/company_partneruserses?$filter=company_email eq \'{email}\'', headers=headers).json()
print(allInfo)
Attempt 2:
Same code but instead of f'https://login.microsoftonline.com/{TENANTID}/oauth2/v2.0/token' its
f'https://login.microsoftonline.com/common/oauth2/v2.0/token'. Error: An exception occurred: [Errno Expecting value] : 0. Because it returns an empty string.
Now I don't know if I am even on the right path or where to go. I know the routes work themselves if the token is correct. I used only SSR with no react and these routes work. But I need the React to be there too. I just don't know what flow to use here to get what I need. The docs make it easy for /me route to work. But the {company}crm.dynamics.com docs don't really provide what I am trying to do.
Additional info after comment:
What 'f'https://{TENANT}api/data/v9.0/company_partneruserses?$filter=company_email eq '{email}'', headers=headers" is trying to get are API keys. Full code :
try:
allInfo = requests.get(
f'https://{TENANT}api/data/v9.0/company_partneruserses?$filter=company_email eq \'{email}\'', headers=headers).json()
partner_value = allInfo['value'][0]['_company_partner_value']
response = requests.get(
f'https://{TENANT}api/data/v9.0/company_partnerses({partner_value})', headers=headers).json()
return {'key': response['company_apikey'], 'secret': response['company_apisecret']}
Then once it has the keys:
def api_authentication(apikey, apisecret):
headers = get_headers() #<-- same headers as above with using dyn_token
response = requests.get(
f'https://{TENANT}api/data/v9.0/company_partnerses?$filter=company_apikey eq \'{apikey}\' and company_apisecret eq \'{apisecret}\'&$select=company_apikey,company_apisecret,_company_account_value,_company_primarycontact_value,blahblah_unassignedhours,company_reporturl', headers=headers).json()
return response
Afterwards I am able to get all the information I am looking for to send back to my frontend for the client to see. (By making multiple request to crm with these keys)
The client_credentials grant that you are using should work, provided the CRM trusts the token issued to the client (your python backend). Please use MSAL library instead of hand crafting the token request. It will save you time and eliminate errors.

Sendgrid Ruby API, Trying to send over Header content in post request

I am trying to send over a Post request to sendgrid to generate an API key for a subuser.
This is what my code currently looks like
body = JSON.parse('{
"name":"My API Key",
"scopes": [
"mail.send",
"alerts.create",
"alerts.read"
]
}')
header = {'On-Behalf-Of' => 'my#email.com'}
sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY'])
response = sg.client.api_keys.post(request_body: body, request_header: header)
This code generates the API but on the main account instead of the Subuser account. The header is what drives where the API key is generated and I can seem to find any sources online that how the correct syntax for sending over the header to sendgrid.
If you could please help I would really appreciate it. Thanks!
I recently had to do this. You need to set the On-Behalf-Of headers when you instantiate the client not when you make the request:
```
#send_grid = API.new(api_key: #api_key, request_headers: {
'On-Behalf-Of' => #username
})
```
Then when you make a request with #send_grid it will send on behalf of the subuser -- and the API key will not show up in the list of api keys on the parent account
If I understand correct, you want to send email "From" another user. On Behalf of is non standard way of doing things.
For eg. https://sendgrid.com/docs/Classroom/Troubleshooting/Authentication/my_emails_are_displaying_as_on_behalf_of_or_via_in_some_mail_clients.html
You may want to try setting from instead of on-behalf-of
"from": {
"email": "from_address#example.com"
},
Refer to: https://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/index.html

Create playlist Deezer API

Im trying to create playlist for user using Deezer API but get error all the time "An active access token must be used to query information about the current use"
response = connection.post do |req|
req.url "user/#{user_id}/playlists"
req.headers['Authorization'] = "Bearer #{acces_token}"
req.headers['Content-Type'] = 'application/json'
req.body = {
title: name,
public: public
}.to_json
end
There is a typo in "access" in "Bearer #{acces_token}"
and
Authorization Code may need to be Authorization
As mentioned here http://developers.deezer.com/api/user/playlists, this action needs a permission "manage_library" from the user to create a new playlist. Just ask for this permission like here http://developers.deezer.com/api/oauth and all will be fine normally.

Instagram API Rate Limit

I'm currently using the Instagram API to like photos and follow users. I'm passing in the access token to make the requests, but for some reason I keep getting client request limit reached. I'm not sure why since the requests are being sent with an access token saved when users authenticate with my app.
here's the gem I'm using to connect to the API in my Rails app: https://github.com/Instagram/instagram-ruby-gem
def self.follow_users(token, tags, user_id)
tags.each do |hashtag|
Instagram.tag_recent_media(hashtag.content).data.each do |data|
Instagram.follow_user(data.user.id, :access_token => token)
end
end
end
Are you passing the user's access token? Or are you passing your own (or your app's) access_token?
If you're passing your own, the reason you're seeing the rate limit error is because Instagram limits Follows to 60/h and Likes to 150/h. You can check the number remaining by inspecting the return HTTP header, and looking for x-ratelimit-remaining.
Sample response:
{
"error_type": "APIError",
"code": 400,
"error_message": "Client request limit reached",
"x-ratelimit-limit": "150",
"x-ratelimit-remaining": "3"
}

Trouble authenticating with Google Content API for Shopping

I'm trying to use OAuth2 for Server to Server Applications in conjunction with Google's Content API for Shopping using the google-api-client gem and Ruby on Rails 3.2.5. Also, I have already set up my merchant account as prescribed in the Content API documentation.
This was the best way I found to be able to:
create/update products in the background
have created products fall under my company's Google Products 'umbrella'
not require every user to authenticate/authorize when their token expires
Using lines 1 - 23 from this sample as a starting point, I've begun to write the following module for use in background jobs:
require 'httparty'
require 'google/api_client'
module GoogleProducts
GOOGLE_CONFIG = YAML.load_file(File.join(Rails.root, "config", "google.yml"))[Rails.env]
CLIENT_ID = "XXXXXXXXXXXX#developer.gserviceaccount.com"
MERCHANT_ID = "XXXXXXX"
SCOPE = "https://www.googleapis.com/auth/structuredcontent"
KEY_FILE_PATH = File.join(Rails.root, "config", "my-privatekey.p12")
KEY_FILE_PASS = "XXXXXXXXXX"
def self.add_item(item_id)
self.fetch_token
xml = self.gen_item_xml(item_id)
headers = {"Content-type" => "application/atom+xml", "Content-Length" => xml.length.to_s}
url = "https://content.googleapis.com/content/v1/#{MERCHANT_ID}/items/products/generic?access_token=#{$gp_token}"
response = HTTParty.post(url, :body => xml, :headers => headers).parsed_response
end
def self.gen_item_xml(item_id)
#building product xml
end
private
def self.fetch_token
api_client = Google::APIClient.new(:authorization => :oauth2)
key = Google::APIClient::PKCS12.load_key(KEY_FILE_PATH, KEY_FILE_PASS)
asserter = Google::APIClient::JWTAsserter.new(CLIENT_ID, SCOPE, key)
begin
api_client.authorization = asserter.authorize
#todo - store in something other than a global
$gp_token = api_client.authorization.access_token
rescue Signet::AuthorizationError => e
puts e.message
ensure
return $gp_token
end
end
end
Everything seemingly works fine - the authentication, the handling of the auth token - until I attempt to actually add an item, which I get the following when I do:
<errors xmlns='http://schemas.google.com/g/2005'>
<error>
<domain>GData</domain>
<code>ServiceForbiddenException</code>
<internalReason>Could not find authenticated customer</internalReason>
</error>
</errors>
Any ideas?
After much anguish and mental toil, I've finally solved my issue!
Since I am using OAuth 2 Server to Server authentication the suggestion hjblok gave didn't apply (thanks for giving it a shot, though!).
I simply added the email address that was associated with my Service Account key from the Google API Console (e.g. XXXXXXXXXXXX#developer.gserviceaccount.com) to my Google Merchant account (Settings > Users on the merchant admin page), and it worked.
If there's any clarification needed, please feel free to comment!
The Google Content API documentation says you need to set it up in the Settings page of the Google Merchant Center:
https://developers.google.com/shopping-content/getting-started/usingapi-products
EDIT rewrote the answer after diving into the Google's API documentation
Did you already try to use Google's OAuth 2.0 playground? I was able to successfully access https://content.googleapis.com/content/v1/#{MERCHANT_ID}/items/products/generic.
In "Step 1" I've chosen the "Content API for Shopping" and then authorized the API with my account.
Then in "Step 2" I've "exchanged authorization code for tokens", which results in a "refresh token" and an "access token".
Then in "Step 3" I've invoked a GET request to https://content.googleapis.com/content/v1/1234567/items/products/generic. Because 1234567 is not a valid MERCHANT_ID it returns an Error. But the Error Messages contains a MERCHANT_ID which actually belongs to your account.
I repeated "Step 3" but now with the correct MERCHANT_ID. Which returns a HTTP/1.1 200 OK with the requested items in the body.
Furthermore I'm not sure, but doesn't Google API expect an Authorization header to be present with the access_token ($gp_token)? Within the OAuth 2.0 playground this Authorization header is used to sent the access_token.
I also found the Structured Content API demo page (https://google-content-api-tools.appspot.com/demo/demo.html), which is more specific to the Content API for Shopping.

Resources