Install
openclaw skills install youtube-reportingYouTube Reporting API integration with managed OAuth. Schedule and download bulk YouTube Analytics reports as CSV files. Use this skill when users want to schedule bulk reporting jobs, list available report types, download daily generated reports, or manage reporting jobs for their YouTube channel. 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-reportingAccess the YouTube Reporting API with managed OAuth authentication. Schedule bulk reporting jobs that generate daily downloadable CSV reports containing channel or playlist analytics data.
# List available report types
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/youtube-reporting/v1/reportTypes')
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-reporting/{native-api-path}
Maton proxies requests to youtubereporting.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 Reporting 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-reporting&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-reporting'}).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-reporting",
"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 Reporting 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-reporting/v1/reportTypes')
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-reporting/v1/reportTypes
Optional Parameters:
| Parameter | Type | Description |
|---|---|---|
pageSize | number | Number of results per page |
pageToken | string | Token for retrieving next page |
includeSystemManaged | boolean | Include system-managed report types (default: false) |
Example:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/youtube-reporting/v1/reportTypes')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"reportTypes": [
{
"id": "channel_basic_a3",
"name": "User activity"
},
{
"id": "channel_demographics_a1",
"name": "Demographics"
},
{
"id": "channel_device_os_a3",
"name": "Device and OS"
},
{
"id": "channel_traffic_source_a3",
"name": "Traffic sources"
}
],
"nextPageToken": "..."
}
Available Channel Report Types:
| Report Type ID | Name |
|---|---|
channel_basic_a3 | User activity |
channel_combined_a3 | Combined |
channel_demographics_a1 | Demographics |
channel_device_os_a3 | Device and OS |
channel_annotations_a1 | Annotations |
channel_cards_a1 | Cards |
channel_end_screens_a1 | End screens |
channel_playback_location_a3 | Playback locations |
channel_province_a3 | Province |
channel_reach_basic_a1 | Reach basic |
channel_reach_combined_a1 | Reach combined |
channel_sharing_service_a1 | Sharing service |
channel_subtitles_a3 | Subtitles |
channel_traffic_source_a3 | Traffic sources |
Available Playlist Report Types:
| Report Type ID | Name |
|---|---|
playlist_basic_a2 | Playlist user activity |
playlist_combined_a2 | Playlist combined |
playlist_device_os_a2 | Playlist device and OS |
playlist_playback_location_a2 | Playlist playback locations |
playlist_province_a2 | Playlist province |
playlist_traffic_source_a2 | Playlist traffic sources |
GET /youtube-reporting/v1/jobs
Optional Parameters:
| Parameter | Type | Description |
|---|---|---|
pageSize | number | Number of results per page |
pageToken | string | Token for retrieving next page |
includeSystemManaged | boolean | Include system-managed jobs (default: false) |
Example:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/youtube-reporting/v1/jobs')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"jobs": [
{
"id": "92f0f65f-18c4-4d15-a815-82223ae93ead",
"reportTypeId": "channel_basic_a3",
"name": "Test User Activity Report",
"createTime": "2026-05-04T22:21:48Z"
}
],
"nextPageToken": "..."
}
GET /youtube-reporting/v1/jobs/{jobId}
Example:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/youtube-reporting/v1/jobs/{job_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:
{
"id": "92f0f65f-18c4-4d15-a815-82223ae93ead",
"reportTypeId": "channel_basic_a3",
"name": "Test User Activity Report",
"createTime": "2026-05-04T22:21:48Z"
}
POST /youtube-reporting/v1/jobs
Content-Type: application/json
{
"reportTypeId": "channel_basic_a3",
"name": "My Daily User Activity Report"
}
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
reportTypeId | string | Yes | Report type ID from reportTypes.list |
name | string | Yes | Display name for the job |
Example:
python <<'EOF'
import urllib.request, os, json
data = json.dumps({
"reportTypeId": "channel_basic_a3",
"name": "Daily User Activity"
}).encode()
req = urllib.request.Request('https://api.maton.ai/youtube-reporting/v1/jobs', 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
Response:
{
"id": "92f0f65f-18c4-4d15-a815-82223ae93ead",
"reportTypeId": "channel_basic_a3",
"name": "Daily User Activity",
"createTime": "2026-05-04T22:21:48.331114Z"
}
DELETE /youtube-reporting/v1/jobs/{jobId}
Example:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/youtube-reporting/v1/jobs/{job_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
resp = urllib.request.urlopen(req)
print(f"Status: {resp.status}")
EOF
Returns empty response on success.
GET /youtube-reporting/v1/jobs/{jobId}/reports
Optional Parameters:
| Parameter | Type | Description |
|---|---|---|
createdAfter | string | Filter reports created after this timestamp (RFC3339 UTC) |
startTimeAtOrAfter | string | Filter by report data start time (on or after) |
startTimeBefore | string | Filter by report data start time (before) |
pageSize | number | Number of results per page |
pageToken | string | Token for retrieving next page |
Example:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/youtube-reporting/v1/jobs/{job_id}/reports')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"reports": [
{
"id": "report-id-123",
"startTime": "2025-04-01T07:00:00Z",
"endTime": "2025-04-02T07:00:00Z",
"downloadUrl": "https://youtubereporting.googleapis.com/...",
"createTime": "2025-04-02T10:00:00Z"
}
],
"nextPageToken": "..."
}
GET /youtube-reporting/v1/jobs/{jobId}/reports/{reportId}
Example:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/youtube-reporting/v1/jobs/{job_id}/reports/{report_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Reports provide a downloadUrl that returns a CSV file. Download via an authorized GET request:
python <<'EOF'
import urllib.request, os
req = urllib.request.Request('{download_url}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
with urllib.request.urlopen(req) as resp:
data = resp.read().decode('utf-8')
print(data[:2000])
EOF
All list endpoints use token-based pagination:
GET /youtube-reporting/v1/reportTypes?pageSize=5&pageToken={nextPageToken}
Response includes nextPageToken when more results exist:
{
"reportTypes": [...],
"nextPageToken": "channel_device_os_a3"
}
Pass the nextPageToken value as pageToken in the next request to retrieve subsequent pages.
const response = await fetch(
'https://api.maton.ai/youtube-reporting/v1/jobs',
{
headers: {
'Authorization': `Bearer ${process.env.MATON_API_KEY}`
}
}
);
const data = await response.json();
console.log(data.jobs);
import os
import requests
# List all jobs
response = requests.get(
'https://api.maton.ai/youtube-reporting/v1/jobs',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}
)
jobs = response.json().get('jobs', [])
# List reports for first job
if jobs:
reports_resp = requests.get(
f'https://api.maton.ai/youtube-reporting/v1/jobs/{jobs[0]["id"]}/reports',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}
)
print(reports_resp.json())
reportTypeId can only exist once; creating a duplicate returns 409 Conflictcurl -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 (missing name or reportTypeId, invalid reportTypeId, deprecated report type) |
| 401 | Invalid or missing Maton API key |
| 403 | Forbidden (cannot create/delete system-managed jobs) |
| 404 | Job or report not found |
| 409 | Conflict (job with same reportTypeId already exists) |
| 429 | Rate limited |
| 4xx/5xx | Passthrough error from YouTube Reporting 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-reporting. For example:https://api.maton.ai/youtube-reporting/v1/jobshttps://api.maton.ai/v1/jobs