通过托管 OAuth 接入 YouTube Analytics 接口,查询频道报告并管理分析分组。
文档
YouTube Reporting
试用通过托管 OAuth 调度 YouTube Reporting 批量任务,下载频道与播放列表的每日 CSV 报告。
它能做什么
通过托管 OAuth 接入 YouTube Reporting API,批量调度生成可下载的 CSV 分析报告。可以枚举可选的报表类型、创建或删除 Reporting 任务、列出与获取已生成的报告,并把 CSV 下载流量走鉴权代理。所有请求都以 MATON_API_KEY 作为 Bearer 令牌发往 api.maton.ai;绑定多个 Google 账号时可通过 Maton-Connection 请求头指定连接。创建和删除任务需要用户事先确认后才会执行。
什么时候用它
- 调度前先列出频道或播放列表的报表类型
- 为流量来源或用户活动创建每日 CSV 报表任务
- 下载已生成好的某一天报告为 CSV
- 管理多个 YouTube 频道对应的 OAuth 连接
技能文档
YouTube Reporting
Access the YouTube Reporting API with managed OAuth authentication. Schedule bulk reporting jobs that generate daily downloadable CSV reports containing channel or playlist analytics data.
Quick Start
# 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
Base URL
https://api.maton.ai/youtube-reporting/{native-api-path}
Maton proxies requests to youtubereporting.googleapis.com and automatically injects your OAuth token.
Authentication
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"
Getting Your API Key
- Sign in or create an account at maton.ai
- Go to maton.ai/settings
- Copy your API key
Connection Management
Manage your YouTube Reporting OAuth connections at https://api.maton.ai.
List Connections
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
Create Connection
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
Get Connection
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.
Delete Connection
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
Specifying Connection
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.
Security & Permissions
- Access is scoped to the YouTube channel(s) associated with the connected Google account.
- Report data is read-only (downloaded CSV files).
- Job creation and deletion require explicit user approval. Before creating or deleting a reporting job, confirm the report type and intended effect with the user.
API Reference
Report Types
List Report Types
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 |
Jobs
List Jobs
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 Job
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"
}
Create Job
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 Job
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.
Reports
List Reports for a Job
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 Report
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
Download Report
Reports provide a downloadUrl pointing at https://youtubereporting.googleapis.com/.... Do not send your MATON_API_KEY to that raw Google host — the key is a Maton credential and must only ever be sent to api.maton.ai. Instead, route the download through the Maton proxy by replacing the Google host with the skill's base URL, so Maton injects the correct Google OAuth token:
python <<'EOF'
import urllib.request, os
# downloadUrl looks like: https://youtubereporting.googleapis.com/v1/media/...
download_url = '{download_url}'
# Rewrite the Google host to the Maton proxy so the request is authenticated
# with your Google OAuth connection (never send MATON_API_KEY to googleapis.com).
proxied_url = download_url.replace(
'https://youtubereporting.googleapis.com/',
'https://api.maton.ai/youtube-reporting/',
)
req = urllib.request.Request(proxied_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
Pagination
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.
Code Examples
JavaScript
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);
Python
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())
Notes
- Reports are generated daily; the first report is available within 24 hours of job creation
- Report data covers a single day (startTime to endTime spans 24 hours)
- Downloaded reports are CSV files with headers in the first row
- A job with a given
reportTypeIdcan only exist once; creating a duplicate returns 409 Conflict - System-managed jobs are auto-generated by YouTube and cannot be created or deleted (403 Forbidden)
- After deleting a job, previously generated reports remain downloadable for up to 60 days
- IMPORTANT: When using curl commands, use
curl -gwhen URLs contain brackets to disable glob parsing - IMPORTANT: When piping curl output to
jqor other commands, environment variables like$MATON_API_KEYmay not expand correctly in some shell environments
Error Handling
| 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 |
Troubleshooting: API Key Issues
- Check that the
MATON_API_KEYenvironment variable is set:
echo $MATON_API_KEY
- Verify the API key is valid by listing connections:
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
Troubleshooting: Invalid App Name
- Ensure your URL path starts with
youtube-reporting. For example:
- Correct:
https://api.maton.ai/youtube-reporting/v1/jobs - Incorrect:
https://api.maton.ai/v1/jobs
Resources
常见问题
- 请求如何鉴权?
- 所有请求都使用 Bearer 令牌(即 MATON_API_KEY 环境变量),发往 api.maton.ai。当绑定了多个 Google 账号时,可通过 Maton-Connection 请求头指定要使用的连接。
- 会写入 YouTube 数据吗?
- 不会。报表数据是只读的。唯一的写入操作是创建或删除 Reporting 任务,且两者都需要用户事先确认后才会执行。
- 能直接从 Google 下载报告吗?
- Google 返回的 downloadUrl 指向 youtubereporting.googleapis.com。该技能会把这类下载改写到 Maton 代理,由代理注入 Google OAuth 令牌;直接把 MATON_API_KEY 发往 Google 主机是不允许的。
相关技能
通过托管 OAuth 代理访问 YouTube Data API v3,搜索与管理视频、播放列表、频道、订阅和评论。
通过托管 OAuth 代理接入 Google Search Console,查询搜索分析数据、管理 sitemap 并查看站点表现。
通过 OAuth 托管的 API 创建与管理 Google Apps Script 项目、部署、版本及远程脚本执行。
通过托管 OAuth 接口查询和管理 Google BigQuery 数据集、表与作业。
通过托管 OAuth,使用 GAQL 查询 Google Ads 广告系列、关键词和效果数据。