Install
openclaw skills install youtube-analytics-apiYouTube Analytics API integration with managed OAuth. Retrieve channel analytics reports and manage video/playlist/channel groups. Use this skill when users want to query YouTube channel metrics (views, watch time, subscribers), analyze performance by dimension (day, country, video), or manage analytics groups. For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway). Requires network access and valid Maton API key.
openclaw skills install youtube-analytics-apiAccess the YouTube Analytics API with managed OAuth authentication. Retrieve channel performance reports (views, watch time, subscribers, revenue) and manage analytics groups for aggregating videos, playlists, or channels.
# Get channel views and watch time for the last 30 days
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/youtube-analytics/v2/reports?ids=channel==MINE&startDate=2025-04-01&endDate=2025-04-30&metrics=views,estimatedMinutesWatched,averageViewDuration')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
https://api.maton.ai/youtube-analytics/{native-api-path}
Maton proxies requests to youtubeanalytics.googleapis.com and automatically injects your OAuth token.
All requests require the Maton API key in the Authorization header:
Authorization: Bearer $MATON_API_KEY
Environment Variable: Set your API key as MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"
Manage your YouTube Analytics OAuth connections at https://api.maton.ai.
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections?app=youtube-analytics&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'youtube-analytics'}).encode()
req = urllib.request.Request('https://api.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"connection": {
"connection_id": "{connection_id}",
"status": "ACTIVE",
"creation_time": "2025-12-08T07:20:53.488460Z",
"last_updated_time": "2026-01-31T20:03:32.593153Z",
"url": "https://connect.maton.ai/?session_token=...",
"app": "youtube-analytics",
"metadata": {}
}
}
Open the returned url in a browser to complete OAuth authorization.
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple YouTube Analytics connections, specify which one to use with the Maton-Connection header:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/youtube-analytics/v2/reports?ids=channel==MINE&startDate=2025-01-01&endDate=2025-01-31&metrics=views')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '{connection_id}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple connections, always include this header to ensure requests go to the intended account.
GET /youtube-analytics/v2/reports?ids={channel_id}&startDate={start}&endDate={end}&metrics={metrics}
Required Parameters:
| Parameter | Type | Description |
|---|---|---|
ids | string | Channel identifier: channel==MINE or channel==CHANNEL_ID |
startDate | string | Start date in YYYY-MM-DD format |
endDate | string | End date in YYYY-MM-DD format |
metrics | string | Comma-separated metrics (e.g., views,likes,comments) |
Optional Parameters:
| Parameter | Type | Description |
|---|---|---|
dimensions | string | Comma-separated dimensions (e.g., day, month, country, video) |
filters | string | Filters in format dimension==value (e.g., country==US) |
sort | string | Sort field; prefix with - for descending (e.g., -views) |
maxResults | integer | Maximum rows to return |
startIndex | integer | 1-based pagination start index |
currency | string | ISO 4217 currency code for revenue metrics (default: USD) |
Example - Daily views for a month:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/youtube-analytics/v2/reports?ids=channel==MINE&startDate=2025-03-01&endDate=2025-03-31&metrics=views,estimatedMinutesWatched,averageViewDuration&dimensions=day&sort=-views&maxResults=10')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Example - Monthly summary:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/youtube-analytics/v2/reports?ids=channel==MINE&startDate=2024-01-01&endDate=2024-12-01&metrics=views,likes,shares,subscribersGained,subscribersLost&dimensions=month&sort=-views')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"kind": "youtubeAnalytics#resultTable",
"columnHeaders": [
{
"name": "day",
"columnType": "DIMENSION",
"dataType": "STRING"
},
{
"name": "views",
"columnType": "METRIC",
"dataType": "INTEGER"
}
],
"rows": [
["2025-03-12", 4],
["2025-03-15", 2]
]
}
Common Metrics:
views - Total video viewslikes - Total likesdislikes - Total dislikescomments - Total commentsshares - Total sharesestimatedMinutesWatched - Total watch time in minutesaverageViewDuration - Average view duration in secondssubscribersGained - New subscribers gainedsubscribersLost - Subscribers lostaverageViewPercentage - Average percentage of video watchedcardClickRate - Card click rateCommon Dimensions:
day - Daily aggregation (YYYY-MM-DD)month - Monthly aggregation (YYYY-MM); endDate must align to 1st of monthcountry - ISO 3166-1 alpha-2 country codevideo - Per-video breakdowndeviceType - Device type (DESKTOP, MOBILE, TABLET, TV, etc.)operatingSystem - OS (ANDROID, IOS, WINDOWS, etc.)liveOrOnDemand - LIVE or ON_DEMANDsubscribedStatus - SUBSCRIBED or UNSUBSCRIBEDGET /youtube-analytics/v2/groups?mine=true
Or by specific IDs:
GET /youtube-analytics/v2/groups?id={group_id}
Parameters:
| Parameter | Type | Description |
|---|---|---|
mine | boolean | Set to true to retrieve all groups owned by authenticated user |
id | string | Comma-separated group IDs to retrieve |
pageToken | string | Token for paginating results |
Response:
{
"kind": "youtube#groupListResponse",
"items": [
{
"kind": "youtube#group",
"etag": "CQVfQEQY1xqZ2O8xKat5QfS2cik",
"id": "JiAz5ne9Wwk",
"snippet": {
"title": "My Video Group",
"publishedAt": "2026-05-04T22:02:12Z"
},
"contentDetails": {
"itemType": "youtube#video"
}
}
],
"nextPageToken": "..."
}
POST /youtube-analytics/v2/groups
Content-Type: application/json
{
"snippet": {
"title": "My New Group"
},
"contentDetails": {
"itemType": "youtube#video"
}
}
Valid item types: youtube#video, youtube#playlist, youtube#channel, youtubePartner#asset
Example:
python <<'EOF'
import urllib.request, os, json
data = json.dumps({
"snippet": {"title": "Top Performers"},
"contentDetails": {"itemType": "youtube#video"}
}).encode()
req = urllib.request.Request('https://api.maton.ai/youtube-analytics/v2/groups', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
PUT /youtube-analytics/v2/groups
Content-Type: application/json
{
"id": "{group_id}",
"snippet": {
"title": "Updated Title"
},
"contentDetails": {
"itemType": "youtube#video"
}
}
Only the group title can be updated.
DELETE /youtube-analytics/v2/groups?id={group_id}
GET /youtube-analytics/v2/groupItems?groupId={group_id}
Response:
{
"kind": "youtube#groupItemListResponse",
"etag": "...",
"items": [
{
"kind": "youtube#groupItem",
"etag": "...",
"groupId": "JiAz5ne9Wwk",
"resource": {
"kind": "youtube#video",
"id": "VIDEO_ID"
}
}
]
}
POST /youtube-analytics/v2/groupItems
Content-Type: application/json
{
"groupId": "{group_id}",
"resource": {
"kind": "youtube#video",
"id": "{video_id}"
}
}
Returns 201 on success, 204 if item already exists in group. Maximum 500 items per group.
DELETE /youtube-analytics/v2/groupItems?id={group_item_id}
Use startIndex and maxResults for paginating report results:
GET /youtube-analytics/v2/reports?ids=channel==MINE&startDate=2025-01-01&endDate=2025-03-31&metrics=views&dimensions=day&maxResults=30&startIndex=1
startIndex is 1-based. Increment by maxResults for subsequent pages.
Use token-based pagination:
GET /youtube-analytics/v2/groups?mine=true&pageToken={nextPageToken}
Response includes nextPageToken when more results exist.
const response = await fetch(
'https://api.maton.ai/youtube-analytics/v2/reports?ids=channel==MINE&startDate=2025-01-01&endDate=2025-01-31&metrics=views,likes,comments&dimensions=day&sort=-views',
{
headers: {
'Authorization': `Bearer ${process.env.MATON_API_KEY}`
}
}
);
const data = await response.json();
console.log(data.rows);
import os
import requests
response = requests.get(
'https://api.maton.ai/youtube-analytics/v2/reports',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'},
params={
'ids': 'channel==MINE',
'startDate': '2025-01-01',
'endDate': '2025-01-31',
'metrics': 'views,likes,comments',
'dimensions': 'day',
'sort': '-views'
}
)
data = response.json()
for row in data.get('rows', []):
print(row)
YYYY-MM-DD formatmonth dimension, endDate must align to the 1st of a month (e.g., 2024-12-01 not 2024-12-31)ids=channel==MINE uses the authenticated user's channel; use channel==CHANNEL_ID for a specific channelgroups.update; use groupItems methods to manage membershipcurl -g when URLs contain brackets to disable glob parsingjq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments| Status | Meaning |
|---|---|
| 400 | Bad request (invalid date range, misaligned month dimension, missing required params) |
| 401 | Invalid or missing Maton API key |
| 403 | Forbidden (insufficient permissions or trying to add items not owned by channel) |
| 429 | Rate limited |
| 4xx/5xx | Passthrough error from YouTube Analytics API |
MATON_API_KEY environment variable is set:echo $MATON_API_KEY
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
youtube-analytics. For example:https://api.maton.ai/youtube-analytics/v2/reports?...https://api.maton.ai/v2/reports?...