This section as Markdown: View Download

YouTube Integration

Connect your agent to a YouTube channel to upload and publish videos and Shorts, edit their details and playlists, list the channel's videos, report performance, and pick video assets for Google Ads Video/Demand Gen campaigns.

Overview

The YouTube integration uses Google OAuth 2.0 with:

  • YouTube Data API v3: channel info, video listings, uploads, video details, playlists, and thumbnails
  • YouTube Analytics API v2: view counts, watch time, subscriber metrics

Skills that use this integration:

  • int-youtube-manage: Uploads and publishes videos and Shorts (title, description, tags, visibility or a scheduled release, playlist, thumbnail), lists channel videos, edits video details and playlists, reports performance, and picks video assets for Google Ads Video/Demand Gen campaigns

Agents that typically enable this integration:

  • Video Creator: to publish the videos it makes to your channel. Add int-youtube-manage with SkillsApply; it adds $1 a month to the Starter price. Video Creator then publishes a finished video when the request asks for it or a YouTube line in its video-preferences says to, and otherwise offers to.
  • Google Ads Manager: for creating Video and Demand Gen campaigns that reference existing YouTube videos

Availability

ModeStatusNotes
"own"AvailableYour own Google Cloud project and OAuth client.
"wiro"Coming soonWiro's shared Google Cloud project is awaiting Google's review. Until then, OAuthConnect in Wiro mode, which is also what you get when you leave out authmethod, returns Wiro-managed OAuth is not enabled for YouTube.

Prerequisites

  • A Wiro API key (see Authentication).
  • A deployed agent (see Agent Overview).
  • A YouTube channel the connecting Google account owns or manages.
  • A Google Cloud project with YouTube Data API v3 and YouTube Analytics API enabled.
  • An HTTPS callback URL.

Connect

Step 1: Create a Google Cloud project and enable the YouTube APIs

  1. console.cloud.google.com → create a project.
  2. APIs & Services → Library → enable:
  3. OAuth consent screen:
    • External user type for multi-tenant use
    • App name, support email
    • Add scopes: youtube, youtube.readonly, yt-analytics.readonly
    • Publish the app (In production). While it is in Testing, Google expires its refresh tokens after 7 days and the agent loses the channel.

Step 2: Create the OAuth client

APIs & Services → Credentials → Create Credentials → OAuth client ID:

  • Application type: Web application
  • Authorized redirect URIs: https://api.wiro.ai/v1/UserAgentOAuth/YTCallback

Copy the client ID and the client secret. If you missed the secret, open the client and use Reset secret.

Step 3: Save the OAuth client to Wiro

curl -X POST "https://api.wiro.ai/v1/UserAgent/CredentialUpsert" \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{
    "useragentguid": "your-useragent-guid",
    "fields": [
      { "credentialkey": "youtube", "fieldname": "clientid", "fieldvalue": "123-abc.apps.googleusercontent.com" },
      { "credentialkey": "youtube", "fieldname": "clientsecret", "fieldvalue": "YOUR_CLIENT_SECRET" },
      { "credentialkey": "youtube", "fieldname": "authmethod", "fieldvalue": "own" }
    ]
  }'

Step 4: Start the connection

curl -X POST "https://api.wiro.ai/v1/UserAgentOAuth/OAuthConnect" \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{
    "useragentguid": "your-useragent-guid",
    "credentialkey": "youtube",
    "redirecturl": "https://your-app.com/settings/integrations",
    "authmethod": "own"
  }'

Send the user to the returned authorizeUrl.

Step 5: Save the channel selection

After consent the user returns with ?yt_connected=true&yt_channels=<URL-encoded-JSON>. Each entry is { id, title, customUrl, subscriberCount }: id is the channel ID, title the channel name, customUrl its custom URL or handle (empty when it has none), and subscriberCount a string ("0" when YouTube returns no count). When the Google account has a single channel, Wiro selects it for you. Otherwise map the user's choice to { channelid, channeltitle } (id becomes channelid, title becomes channeltitle) and call SetPickerAccounts:

curl -X POST "https://api.wiro.ai/v1/UserAgentOAuth/SetPickerAccounts" \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{
    "useragentguid": "your-useragent-guid",
    "credentialkey": "youtube",
    "accounts": [
      { "channelid": "UC...", "channeltitle": "My Channel" }
    ]
  }'

Pass multiple { channelid, channeltitle } entries to authorize the agent against several channels at once.

Disconnect

curl -X POST "https://api.wiro.ai/v1/UserAgentOAuth/OAuthDisconnect" \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{
    "useragentguid": "your-useragent-guid",
    "credentialkey": "youtube"
  }'

Status

curl -X POST "https://api.wiro.ai/v1/UserAgentOAuth/OAuthStatus" \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{
    "useragentguid": "your-useragent-guid",
    "credentialkey": "youtube"
  }'

Response:

{
  "result": true,
  "connected": true,
  "accounts": [
    { "id": "UC...", "name": "My Channel" }
  ],
  "connectedat": "2026-04-17T12:00:00.000Z",
  "tokenexpiresat": "2026-04-17T13:00:00.000Z",
  "errors": []
}

accounts[] carries one entry per selected channel (id = channelid, name = channeltitle).

API Reference

POST /UserAgentOAuth/OAuthConnect

ParameterTypeRequiredDescription
useragentguidstringYesAgent instance GUID.
credentialkeystringYes"youtube".
redirecturlstringYesAny HTTPS URL you control (or http://localhost / http://127.0.0.1 for development).
authmethodstringNo"own". Omitted, it means "wiro", which is not available yet.

GET /UserAgentOAuth/YTCallback

Server-side endpoint invoked by Google. You don't call it: you register it as the Authorized redirect URI of your OAuth client. Wiro then sends the browser to your redirecturl with yt_connected=true&yt_channels=<JSON> (a URL-encoded array of { id, title, customUrl, subscriberCount }) or yt_error=<code>. The callback path is per-provider: YouTube's stays YTCallback. When you pass a channel to SetPickerAccounts, map it to { channelid: id, channeltitle: title }.

POST /UserAgentOAuth/SetPickerAccounts

ParameterTypeRequiredDescription
useragentguidstringYesAgent instance GUID.
credentialkeystringYes"youtube".
accountsarrayYesOne or more { channelid, channeltitle } entries.

Response: { result, accounts: [{id, name}, ...], errors }. Triggers agent restart if running.

POST /UserAgentOAuth/OAuthStatus

Body: { useragentguid, credentialkey: "youtube" }. Response: connected, accounts: [{id, name}, ...] (one entry per selected channel: id = channelid, name = channeltitle), connectedat, tokenexpiresat.

POST /UserAgentOAuth/OAuthDisconnect

Body: { useragentguid, credentialkey: "youtube" }. Clears the tokens and the selected channels in Wiro. Your Client ID and Client Secret are kept. Wiro does not ask Google to revoke the authorization.

What the agent does with this integration

Uploading and publishing videos

Ask the agent to put a video on YouTube, for example one it made with Video Creator. It uploads the video to the selected channel and replies with the link.

  • Regular videos and Shorts. One upload covers both: YouTube files a vertical (9:16) or square video of up to 3 minutes as a Short and anything else as a regular video. A Short needs no #Shorts tag.
  • Details. Title (up to 100 characters), description (up to 5,000), tags, category, language, the made-for-kids setting, and visibility: public, unlisted, private, or a scheduled release time. A video that shows realistic AI-generated people or scenes is marked as altered or synthetic content, and YouTube labels it.
  • Playlist and thumbnail. The agent can add the video to a playlist and set a frame of it as the thumbnail. YouTube accepts custom thumbnails for regular videos on verified channels.
  • Approval. Uploads go through the agent's approval policy (the approval-policy custom skill). A request that already says to upload or publish is the approval; otherwise the agent shows the title, description, tags, playlist and visibility first and uploads after you approve.
  • Drafts. Ask for a private or unlisted upload, and ask the agent to publish it later: it makes the video public, or schedules it, and keeps the synthetic-content label.
  • No duplicates. When an upload fails, the agent looks for the video among the channel's uploads before it tries once more.

The reply gives the video's link, its visibility or scheduled time, and its playlist.

Videos from an unaudited Google Cloud project stay private. YouTube restricts videos uploaded through a Google Cloud project created after 28 July 2020 that has not passed the YouTube API audit to private viewing, whatever visibility was asked for. The agent reads the video back after the upload; if YouTube has locked it, the agent tells you once and does not upload it again. Request the audit for the project behind your OAuth client with YouTube's API audit form. Until it passes, download the video from the chat and upload it in YouTube Studio.

Channel video listing

Agent lists channel uploads:

Operator → "show my last 20 YouTube videos"
Agent → GET /youtube/v3/playlistItems?playlistId=UU{channel}
     returns 20 items with video IDs, titles, dates, durations

Video asset for Google Ads campaigns

Google Ads Manager agent uses this skill to pick video assets for Video and Demand Gen campaigns:

Agent → /youtube-manage list last 30 days of videos
     → picks top 3 by views
     → /googleads-manage create Video campaign with these as creatives

Performance analytics

Agent queries video-level metrics:

Operator → "which videos performed best last month?"
Agent → POST /youtubeAnalytics/v2/reports
     with dimensions=[video], metrics=[views, averageViewDuration, estimatedMinutesWatched]

Skill reference

Troubleshooting

SymptomCauseFix
Wiro-managed OAuth is not enabled for YouTube in OAuthConnect's errors[]Wiro mode isn't available yet, and it is the default when authmethod is left outSave your OAuth client (Step 3) and call OAuthConnect with "authmethod": "own"
YouTube credentials not configuredauthmethod: "own" without a saved clientid and clientsecretSave them (Step 3), then retry
yt_error=no_accounts on your redirecturlGoogle listed no YouTube channel for this account, and Wiro saved nothing: the account has no channel, or the YouTube Data API v3 is not enabled in your projectEnable the API (Step 1), or have the user create a channel, then call OAuthConnect again
quotaExceededDaily quota hitWait 24h or request higher quota from Google
channelNotFoundChannel deleted or movedUser re-selects via SetPickerAccounts
invalid_grantRefresh token expired or revoked; a consent screen still in Testing expires it after 7 daysPublish the consent screen, then re-connect via OAuthConnect
A video uploaded as public or unlisted stays privateThe Google Cloud project hasn't passed the YouTube API auditRequest the audit; until then upload the video in YouTube Studio

redirect_uri_mismatch on Google's page

The Authorized redirect URIs of your OAuth client don't include https://api.wiro.ai/v1/UserAgentOAuth/YTCallback exactly as written. Google stops on its own error page, so nothing comes back to your redirecturl. Add the URI (Step 2) and connect again.