YouTube Publishing
Learn how to connect YouTube channels and upload videos with metadata and custom thumbnails.
Connecting YouTube Channel
Prerequisites
- A YouTube channel
- Google account with channel access
- Signed in to Boring Dashboard
Connection Steps
- Click the "Connect YouTube" button on the dashboard
- Sign in to Google (if not already logged in)
- Select your YouTube channel
- Review and grant the required permissions:
youtube.upload- Upload videos to your channelyoutube- Manage your YouTube accountyoutube.readonly- View your YouTube account
- Click "Allow" to complete the authorization
Your YouTube channel will now appear in the Authorized Accounts list with:
- Channel name
- Channel thumbnail
- Platform badge (YouTube)
- Unique Account ID (click "Copy ID" to get it)
- Disconnect option
Token Information
- Token Type: OAuth 2.0 Access Token with Refresh Token
- Expiration: Access token expires in 1 hour
- Auto-refresh: Enabled (refresh token used to get new access tokens)
- Re-authorization: Only needed if refresh token is revoked
Supported Content Types
YouTube supports video uploads with rich metadata:
| Feature | Description | Required | Limits |
|---|---|---|---|
| Video | Video file URL | Yes | MP4, MOV, AVI, etc. |
| Title | Video title | Yes | Max 100 characters |
| Description | Video description | No | Max 5000 characters |
| Tags | Video tags/keywords | No | Max 500 tags |
| Thumbnail | Custom thumbnail image | No | JPG, PNG (1280x720 recommended) |
| Privacy | Privacy setting | No | Defaults to 'public' |
Publishing Examples
1. Basic Video Upload (Title Only)
{
"post": {
"accountId": "your-youtube-channel-account-id",
"content": {
"text": "My Awesome Video Title",
"mediaUrls": ["https://example.com/video.mp4"],
"platform": "youtube"
},
"target": {
"targetType": "youtube"
}
}
}
Result: Video uploaded with title, no description.
2. Video with Title and Description
The text field uses a special format with \n\n (two newlines) to separate title and description:
{
"post": {
"accountId": "your-youtube-channel-account-id",
"content": {
"text": "Complete Guide to API Integration\n\nIn this comprehensive tutorial, we'll walk through the entire process of integrating our API into your application. Perfect for beginners and advanced developers alike!\n\n#API #Tutorial #Programming",
"mediaUrls": ["https://example.com/tutorial-video.mp4"],
"platform": "youtube"
},
"target": {
"targetType": "youtube"
}
}
}
Text Format:
- Before
\n\n: Video title (max 100 chars) - After
\n\n: Video description (max 5000 chars) - Hashtags: Any
#tagin description becomes a video tag
Result:
- Title: "Complete Guide to API Integration"
- Description: "In this comprehensive tutorial..."
- Tags: ["API", "Tutorial", "Programming"]
3. Video with Custom Thumbnail
To upload a video with a custom thumbnail, include the thumbnail URL as the second item in mediaUrls:
{
"post": {
"accountId": "your-youtube-channel-account-id",
"content": {
"text": "Product Launch Event 2025\n\nJoin us for the biggest product launch of the year! See all the new features and innovations we've been working on. Don't miss out! #ProductLaunch #Tech #Innovation",
"mediaUrls": [
"https://storage.example.com/launch-video.mp4",
"https://storage.example.com/thumbnail.jpg"
],
"platform": "youtube"
},
"target": {
"targetType": "youtube"
}
}
}
Media URLs Array:
mediaUrls[0]: Video file URL (required)mediaUrls[1]: Thumbnail image URL (optional)
Result: Video uploaded with title, description, tags, and custom thumbnail.
Thumbnail Requirements:
- Format: JPG, PNG
- Resolution: 1280x720 (recommended), min 640x360
- Aspect ratio: 16:9
- Max size: 2MB
- URL: Must be publicly accessible
API Request Format
Full Example with Python
import requests
API_URL = "https://boring.aiagent-me.com/v2/posts"
API_KEY = "boring_xxxxxxxxxxxxx"
ACCOUNT_ID = "your-youtube-channel-account-id"
# Video with title, description, and thumbnail
post_data = {
"post": {
"accountId": ACCOUNT_ID,
"content": {
"text": "Ultimate Travel Vlog: Tokyo 2025\n\nExplore the streets of Tokyo with me in this amazing travel vlog! From traditional temples to modern technology, we'll see it all. Subscribe for more travel content!\n\n#Tokyo #Travel #Vlog #Japan #Adventure",
"mediaUrls": [
"https://storage.googleapis.com/my-bucket/tokyo-vlog.mp4",
"https://storage.googleapis.com/my-bucket/tokyo-thumbnail.jpg"
],
"platform": "youtube"
},
"target": {
"targetType": "youtube"
}
}
}
headers = {
"boring-api-key": API_KEY,
"Content-Type": "application/json"
}
response = requests.post(API_URL, headers=headers, json=post_data)
result = response.json()
if result.get("success"):
print(f"Video uploaded successfully!")
print(f"Video ID: {result['video_id']}")
print(f"Watch at: {result['video_url']}")
print(f"Thumbnail uploaded: {result.get('thumbnail_uploaded', False)}")
else:
print(f"Upload failed: {result.get('error')}")
Success Response
{
"success": true,
"message": "Post published successfully",
"postSubmissionId": "uuid-here",
"platform": "youtube",
"post_type": "video",
"video_id": "dQw4w9WgXcQ",
"video_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"thumbnail_uploaded": true
}
Text Format Guide
Understanding the \n\n Separator
The text field uses \n\n (two newline characters) as a separator between title and description.
β Wrong - Single newline \n:
{
"text": "My Title\nMy Description"
}
Result: "My Title\nMy Description" becomes the title (no description)
β
Correct - Double newline \n\n:
{
"text": "My Title\n\nMy Description"
}
Result:
- Title: "My Title"
- Description: "My Description"
Examples for Different Languages
Python:
text = "Video Title\n\nThis is the description with #hashtags"
# or using triple quotes for readability:
text = """Video Title
This is the description with #hashtags"""
JavaScript:
const text = "Video Title\n\nThis is the description with #hashtags";
// or using template literals:
const text = `Video Title
This is the description with #hashtags`;
cURL:
curl -X POST https://boring.aiagent-me.com/v2/posts \
-H "boring-api-key: boring_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"post": {
"accountId": "your-account-id",
"content": {
"text": "Video Title\n\nVideo description here",
"mediaUrls": ["https://example.com/video.mp4"],
"platform": "youtube"
},
"target": {"targetType": "youtube"}
}
}'
Video Requirements
Supported Formats
- Containers: MP4, MOV, AVI, WMV, FLV, 3GPP, WebM, MPEG-PS
- Codecs: H.264, H.265, VP9, AV1
- Audio: AAC, MP3, Vorbis, Opus
File Specifications
- Max file size: No hard limit (tested up to 256GB)
- Max duration: 12 hours (15 minutes for unverified accounts)
- Recommended resolution: 1080p (1920x1080) or higher
- Recommended bitrate: 8 Mbps for 1080p, 16 Mbps for 4K
- Aspect ratio: 16:9 (recommended), 4:3, 9:16 (Shorts)
Upload Process
- Download: Video is downloaded from the provided URL
- Upload: Video is uploaded to YouTube using resumable upload
- Processing: YouTube processes the video (may take several minutes)
- Thumbnail: Custom thumbnail is uploaded (if provided)
- Publishing: Video becomes available based on privacy setting
Upload Progress: The API shows progress in server logs:
[YOUTUBE] Upload progress: 33%
[YOUTUBE] Upload progress: 67%
[YOUTUBE] Upload progress: 100%
[YOUTUBE] Video uploaded successfully! Video ID: abc123
[YOUTUBE] Thumbnail uploaded successfully
Privacy Settings
Currently, all videos are uploaded as public by default. Future updates will support:
public- Anyone can viewunlisted- Only people with the link can viewprivate- Only you can viewscheduled- Publish at specific time
Troubleshooting
Common Errors
Error: "Video URL is required"
- Cause: No video URL in
mediaUrlsarray - Solution: Add video URL as first element:
"mediaUrls": ["video.mp4"]
Error: "Failed to download video"
- Cause: Video URL is not accessible
- Solution:
- Verify URL is publicly accessible
- Test with:
curl -I https://your-video-url.mp4 - Ensure no authentication required
Error: "YouTube service not initialized"
- Cause: OAuth token issues
- Solution: Disconnect and reconnect your YouTube channel
Error: "Thumbnail upload failed"
- Cause: Invalid thumbnail or permission issues
- Note: Video upload succeeded, only thumbnail failed
- Solution:
- Check thumbnail meets requirements (1280x720, JPG/PNG)
- Verify thumbnail URL is publicly accessible
- Thumbnail can be changed later in YouTube Studio
Upload Taking Too Long?
Video upload time depends on:
- Video size: Larger files take longer
- Your connection: Upload speed to cloud storage
- YouTube processing: Additional time after upload
Typical times:
- 100MB video: 30-60 seconds
- 500MB video: 2-5 minutes
- 1GB video: 5-10 minutes
Best Practices
- Test with small videos first - Ensure setup works correctly
- Use reliable hosting - Google Cloud Storage, AWS S3, etc.
- Optimize video files - Use H.264 codec, compress if needed
- Create engaging thumbnails - 1280x720, bright colors, clear text
- Write SEO-friendly descriptions - Include relevant keywords
- Use hashtags strategically - 3-5 relevant tags in description
- Monitor upload status - Check dashboard for errors
Publishing History
View all your YouTube uploads in the dashboard:
- Sign in to Boring Dashboard
- Scroll to "Recent Posts" section
- Filter by platform: YouTube
Each entry shows:
- Video title
- Video ID and YouTube URL
- Upload status (published/failed)
- Thumbnail status
- Timestamp
- Error message (if failed)
Rate Limits
YouTube API quotas apply:
- Default quota: 10,000 units/day
- Video upload: 1,600 units per upload
- Thumbnail upload: 50 units per upload
Daily limit: ~6 videos/day with default quota
To increase quota, apply for higher limits in Google Cloud Console.
Boring handles quota errors gracefully and returns appropriate error messages.
Advanced Features
Multiple Channels
You can connect multiple YouTube channels to the same Boring account. Each channel gets a unique Account ID.
Example workflow:
- Connect Channel A (get Account ID:
aaa-111) - Connect Channel B (get Account ID:
bbb-222) - Upload to Channel A using
accountId: "aaa-111" - Upload to Channel B using
accountId: "bbb-222"
Batch Uploads
Upload multiple videos programmatically:
videos = [
{
"title": "Episode 1: Introduction",
"description": "Welcome to our series!",
"video_url": "https://example.com/ep1.mp4",
"thumbnail_url": "https://example.com/ep1-thumb.jpg"
},
{
"title": "Episode 2: Getting Started",
"description": "Let's dive deeper!",
"video_url": "https://example.com/ep2.mp4",
"thumbnail_url": "https://example.com/ep2-thumb.jpg"
}
]
for video in videos:
post_data = {
"post": {
"accountId": ACCOUNT_ID,
"content": {
"text": f"{video['title']}\n\n{video['description']}",
"mediaUrls": [video['video_url'], video['thumbnail_url']],
"platform": "youtube"
},
"target": {"targetType": "youtube"}
}
}
response = requests.post(API_URL, headers=headers, json=post_data)
print(f"Uploaded: {video['title']} - {response.json()}")
# Wait between uploads to avoid rate limits
time.sleep(60)
Quick Reference
Minimal Upload (Title + Video)
{
"post": {
"accountId": "your-account-id",
"content": {
"text": "Video Title",
"mediaUrls": ["https://example.com/video.mp4"],
"platform": "youtube"
},
"target": {"targetType": "youtube"}
}
}
Full Upload (Title + Description + Thumbnail)
{
"post": {
"accountId": "your-account-id",
"content": {
"text": "Video Title\n\nDetailed description with #tags",
"mediaUrls": [
"https://example.com/video.mp4",
"https://example.com/thumbnail.jpg"
],
"platform": "youtube"
},
"target": {"targetType": "youtube"}
}
}
Next Steps
- Facebook Publishing - Learn about Facebook
- Instagram Publishing - Learn about Instagram
- Threads Publishing - Learn about Threads
- API Reference - Complete API documentation
- Examples - More code examples