Rawugc API
Quick answer
- 01What is it?
- Procedural knowledge for agents to call the RawUGC API. All requests require an API key from the RawUGC dashboard, passed via environment variable. It stands out by giving rawugc API a defined shape, so the agent asks for better context and returns a more usable result.
- 02Inputs
- Context the agent needs: your goals, audience, constraints, and any source material the skill asks for.
- 03Output
- A ready-to-use result: the analysis, copy, or recommendations the agent produces.
Add this skill
Install as a package
Installs this one skill package for your coding agent, including any supporting files that skill ships with โ not every skill in the repository. Read the tutorial.
$ npx skills add tfcbot/rawugc-skills --skill rawugc-apiSkill instructions
The instruction file for this skill. The skill also includes other files you need to install to use it.
RawUGC API
Procedural knowledge for agents to call the RawUGC API. All requests require an API key from the RawUGC dashboard, passed via environment variable.
Authentication
- Environment variable: Read the API key from
RAWUGC_API_KEY. The key is created in the RawUGC dashboard and must be kept secret; do not hardcode or log it. - Header: Send on every request:
Authorization: Bearer <value of RAWUGC_API_KEY>. - If
RAWUGC_API_KEYis missing or empty, inform the user they must set it and obtain a key from the RawUGC dashboard.
Base URL
- Production:
https://rawugc.com/api/v1 - All paths below are relative to this base.
API Versioning
RawUGC uses date-based API versioning. The current latest version is 2026-03-06.
RawUGC-Versionrequest header: Override the version per-request (recommended).- API key pinned version: Set when creating the key in the dashboard.
- Fallback: Latest version (
2026-03-06) if neither is set.
Always send RawUGC-Version: 2026-03-06 in requests to ensure consistent behavior.
Video Generation
POST /videos/generate
Initiate video generation.
Request body (JSON):
| Field | Type | Required | Description |
|---|---|---|---|
model | string | Yes | sora-2-text-to-video, sora-2-image-to-video, kling-2.6/motion-control, veo3, veo3_fast |
prompt | string | For text-to-video / veo3 | Text description (1-5000 chars) |
imageUrls | string[] | For image-to-video / kling | URLs, max 10. Veo3/veo3_fast accept up to 2 optional images. |
videoUrls | string[] | For kling | URLs, max 1. Required for kling-2.6/motion-control |
aspectRatio | string | No | Sora: portrait/landscape. Veo3: 16:9/9:16/Auto |
nFrames | string | No | "10" or "15" (Sora only) |
selectedCharacter | string | No | Character username (e.g. rawugc.mia) |
characterOrientation | string | No | image or video (kling only) |
mode | string | No | 720p or 1080p (kling only) |
Response (201): videoId, model, status, creditsUsed, newBalance, estimatedCompletionTime, createdAt.
GET /videos/:videoId
Get video status. Returns videoId, status, model, prompt, creditsUsed, url (when completed), createdAt, completedAt, failCode, failMessage, versions (edit history array).
GET /videos
List videos. Query: status, limit (1-100, default 50), page. Returns videos array + pagination.
POST /videos/captions
Add styled captions to a completed video. Costs 1 credit.
| Field | Type | Required | Description |
|---|---|---|---|
videoId | string | Yes | Video identifier (vid_xxx) |
language | string | No | Language code (e.g. en). Defaults to auto-detect |
Response (200): videoId, url, version, operation, creditsUsed.
POST /videos/overlay
Add text overlay to a completed video.
| Field | Type | Required | Description |
|---|---|---|---|
videoId | string | Yes | Video identifier (vid_xxx) |
text | string | Yes | Overlay text (1-500 chars) |
position | string | No | top, center, or bottom |
fontSize | integer | No | 8-200 pixels |
topBottomMargin | integer | No | 0-500 pixels |
strokeThickness | number | No | 0-10 |
Response (200): videoId, url, version, operation, creditsUsed.
Image Generation
POST /images/generate
Generate AI images using Nano Banana models. Async -- poll GET /images/:imageId.
| Field | Type | Required | Description |
|---|---|---|---|
model | string | Yes | nano-banana-2 (text-to-image, 4 credits) or google/nano-banana-edit (image editing, 2 credits) |
prompt | string | Yes | Text description or edit instruction (1-20000 chars) |
imageUrls | string[] | For editing | Source images. Required for google/nano-banana-edit. Optional for nano-banana-2 (reference images, max 14). |
aspectRatio | string | No | For nano-banana-2: 1:1, 16:9, 9:16, auto, etc. |
imageSize | string | No | For google/nano-banana-edit: 1:1, 16:9, 9:16, auto, etc. |
resolution | string | No | For nano-banana-2: 1K, 2K, 4K |
outputFormat | string | No | png, jpeg, jpg |
googleSearch | boolean | No | Use Google Web Search grounding (nano-banana-2 only) |
Response (201): imageId, model, status, creditsUsed, newBalance, estimatedCompletionTime, createdAt.
GET /images/:imageId
Get image status. Returns imageId, status, model, prompt, url (when completed), imageSize, resolution, outputFormat, creditsUsed, createdAt, completedAt, failCode, failMessage.
GET /images
List images. Query: status, limit (1-100, default 20), page. Returns images array + pagination.
Music Generation
POST /music/generate
Generate AI music using Suno models. 3 credits per generation. Async -- poll GET /music/:musicId.
| Field | Type | Required | Description |
|---|---|---|---|
prompt | string | Yes | Music description (1-2000 chars) |
model | string | No | V3_5, V4, V4_5, V4_5PLUS, V4_5ALL, V5 (default: V5) |
instrumental | boolean | No | Instrumental only, no vocals (default: true) |
title | string | No | Track title (max 200 chars). Enables custom mode with style. |
style | string | No | Style descriptor (max 500 chars, e.g. lo-fi hip hop) |
Response (201): musicId, model, status, creditsUsed, newBalance, estimatedCompletionTime, createdAt.
GET /music/:musicId
Get music status. Returns musicId, status, model, prompt, audioUrl (when completed), albumArtUrl, duration, title, creditsUsed, createdAt, completedAt, failCode, failMessage.
GET /music
List music tracks. Query: status, limit (1-100, default 20), page. Returns tracks array + pagination.
Upload
POST /upload
Upload a video or image file. Returns a URL for use in generation requests (imageUrls, videoUrls) or analyze-video. Max 100MB.
Request: multipart/form-data with file field. Accepted types: video/mp4, video/quicktime, video/webm, image/png, image/jpeg, image/webp.
Response (200): url, contentType, size.
Characters
GET /characters
List all available AI characters (built-in + custom). Returns characters array, count, adminCount, userCount.
GET /characters/:characterId
Get a character by ID. Returns _id, username, displayName, description, videoPreviewUrl, type (admin/user), isActive, createdAt, updatedAt.
Personas (CRUD)
Personas define target audiences for content plan generation.
- GET /personas -- List all. Returns
personasarray +count. - POST /personas -- Create. Body:
name(required, max 200),description(required, max 5000). Returnsid. - GET /personas/:personaId -- Get one.
- PATCH /personas/:personaId -- Update. Body:
name,description(both optional). - DELETE /personas/:personaId -- Delete.
PersonaResponse: _id, organizationId, name, description, createdAt, updatedAt.
Messaging (CRUD)
Brand/positioning messaging templates.
- GET /messaging -- List all. Returns
messagesarray +count. - POST /messaging -- Create. Body:
name(required, max 200),body(required, max 5000). Returnsid. - GET /messaging/:messageId -- Get one.
- PATCH /messaging/:messageId -- Update. Body:
name,body(both optional). - DELETE /messaging/:messageId -- Delete.
MessagingResponse: _id, organizationId, name, body, createdAt, updatedAt.
Products (CRUD)
Products for video generation.
- GET /products -- List all. Returns
productsarray +count. - POST /products -- Create. Body:
name(required, max 200),photos(required, URL array),description(max 1000),messaging(max 5000). Returnsid. - GET /products/:productId -- Get one.
- PATCH /products/:productId -- Update. Body:
name,description,photos,messaging(all optional). - DELETE /products/:productId -- Delete.
ProductResponse: _id, name, description, photos, messaging, createdAt, updatedAt.
Styles (CRUD)
Video/image creative styles with optional prompt templates.
- GET /styles -- List all (built-in + custom). Query:
type(video/image). Returnsstylesarray +count. - POST /styles -- Create. Body:
name(required, max 200),description(max 1000),type(video/image),aspectRatio(portrait/landscape/square),promptTemplate(max 5000, supports{productName},{messaging},{character}placeholders). Returnsid. - GET /styles/:styleId -- Get one.
- PATCH /styles/:styleId -- Update. All fields optional.
- DELETE /styles/:styleId -- Delete.
StyleResponse: _id, name, description, type, aspectRatio, styleId, promptTemplate, isAdmin, isStandard.
Social Scheduling
GET /social/accounts
List connected social accounts (max 3 per org). Returns accounts array + count. Each account: accountId, platform (tiktok/instagram/youtube), username, displayName, profilePicture, isActive.
POST /social/accounts
Sync connected accounts from the scheduling provider. Returns { success: boolean }.
DELETE /social/accounts/:accountId
Disconnect a social account. Returns { success: boolean }.
POST /social/posts
Schedule, draft, or immediately publish a video to social media.
| Field | Type | Required | Description |
|---|---|---|---|
videoUrl | string | Yes | URL of video to post |
accountIds | string[] | Yes | Target account IDs |
mode | string | Yes | schedule, draft, or now |
scheduledFor | integer | For schedule | Unix timestamp (ms) |
timezone | string | No | IANA timezone (default: UTC) |
content | string | No | Caption (max 2200 chars) |
videoId | string | No | RawUGC video ID to link |
publishToInbox | boolean | No | Send to TikTok Creator Inbox |
tiktokPrivacyLevel | string | No | SELF_ONLY, PUBLIC_TO_EVERYONE, MUTUAL_FOLLOW_FRIENDS, FOLLOWER_OF_CREATOR |
tiktokAllowComment | boolean | No | Allow TikTok comments |
tiktokAllowDuet | boolean | No | Allow TikTok duets |
tiktokAllowStitch | boolean | No | Allow TikTok stitches |
tiktokCommercialContentType | string | No | none, brand_organic, brand_content |
Response (201): SocialPost object.
GET /social/posts
List posts. Query: fromDate (ms), toDate (ms), includeDrafts (boolean). Returns posts array + count.
GET /social/posts/:postId
Get a post.
PATCH /social/posts/:postId
Update a post. Body: content, scheduledFor, timezone, accountIds (at least one field required).
DELETE /social/posts/:postId
Delete a post. Returns { success: boolean }.
POST /social/posts/:postId/reschedule
Reschedule a post. Body: scheduledFor (required, ms), timezone.
POST /social/posts/:postId/publish
Immediately publish a draft post.
SocialPost: postId, platforms, status (draft/scheduled/published/failed), scheduledFor, timezone, content, videoUrl, createdAt, publishedAt.
Viral Library
GET /viral-library/videos/:videoId
Get a viral library video with full AI analysis (hooks, keyframes, performance insights). Returns ViralLibraryVideo.
GET /viral-library/search
Semantic search across analyzed videos. Query: q (required, natural language), limit (1-50, default 20). Returns results (array of { video, score }), query, total.
Research
POST /scrape-tiktok
Scrape TikTok videos. Costs 3 credits.
| Field | Type | Required | Description |
|---|---|---|---|
query | string | Yes | Search keyword, hashtag, or query (max 500) |
mode | string | No | keyword, hashtag, search (default: keyword) |
limit | integer | No | 1-10 (default: 10) |
Response (200): scrapeId (use with content-plans), count, videos (array with id, url, author, description, stats, duration, hashtags, thumbnail, videoUrl).
POST /content-plans
Generate a content plan from scraped videos. Costs 3 credits.
| Field | Type | Required | Description |
|---|---|---|---|
scrapeId | string | Yes | From scrape-tiktok response |
brief | string | Yes | Content plan goals (max 5000) |
Response (200): planId, scrapeId, brief, topWins, gapsToTest, blueprints (array with category, strategy, evidence, contentIdeas).
GET /content-plans
List all content plans. Returns plans array + count.
POST /analyze-video
Analyze any video URL (social links or direct URLs). Costs 1 credit. Max 150MB.
| Field | Type | Required | Description |
|---|---|---|---|
videoUrl | string | Yes | Video URL to analyze |
prompt | string | No | Custom analysis prompt (max 5000) |
Response (200): summary, hook, keyframes (array with timestamp, type, description, visual, audio, text), durationSeconds, tags, whyItPerformed, attributesToCopy, hooksToTest.
Errors
All error responses use RFC 7807 Problem Details (JSON): type, title, status, detail, instance, errors.
| Status | Meaning |
|---|---|
| 400 | Validation error. Surface detail and errors to user. |
| 401 | Auth error. Check RAWUGC_API_KEY. |
| 402 | Insufficient credits. Add credits in dashboard. |
| 403 | Insufficient scope. API key lacks permissions. |
| 404 | Resource not found. |
| 429 | Rate limit exceeded. Check X-RateLimit-Reset header. |
| 500 | Server error. Retry or contact support. |
Rate Limits
- API Key: 10 req/min. Session: 20 req/min.
- Headers:
X-RateLimit-Limit,X-RateLimit-Remaining,X-RateLimit-Reset(unix timestamp).
Workflow: Generate then poll
- Generate: POST to the generation endpoint. Note the returned ID (
videoId/imageId/musicId). - Poll: GET the status endpoint periodically (10-30s). Use exponential backoff.
- Finish: When
status === 'completed', use the result URL. Whenfailed, surface error to user. - Edit (video only): POST to
/videos/captionsor/videos/overlay.
For full request/response shapes, see reference.md.
Supporting file: reference.md
RawUGC API -- Request/Response Reference
Condensed shapes for agent lookups. Base URL: https://rawugc.com/api/v1. Auth: Authorization: Bearer <RAWUGC_API_KEY>. Version: RawUGC-Version: 2026-03-06.
Video Generation
POST /videos/generate
Request (application/json)
model(required):sora-2-text-to-video|sora-2-image-to-video|kling-2.6/motion-control|veo3|veo3_fastprompt(optional, required for text-to-video/veo3): string, 1-5000 charsimageUrls(optional, required for image-to-video/kling): string[], max 10. Veo3/veo3_fast accept up to 2.videoUrls(optional, required for kling): string[], max 1aspectRatio(optional): Sora:portrait|landscape. Veo3:16:9|9:16|AutonFrames(optional, Sora only):"10"|"15"selectedCharacter(optional): stringcharacterOrientation(optional, kling only):image|videomode(optional, kling only):720p|1080p
Response 201: videoId (vid_xxx), model, status, creditsUsed, newBalance, estimatedCompletionTime, createdAt (ms epoch)
GET /videos/{videoId}
Response 200: videoId, status (pending|processing|completed|failed), model, prompt?, creditsUsed, url? (completed), createdAt, completedAt?, failCode?, failMessage?, versions? (MediaVersion[])
MediaVersion: videoId, version (int), url, operation? (captions|overlay), createdAt
GET /videos
Query: status?, limit? (1-100, default 50), page? (default 1)
Response 200: videos (VideoResponse[]), pagination (total, page, pageSize, hasMore)
POST /videos/captions
Request: videoId (required), language? (e.g. en)
Response 200 (EditResponse): videoId, url, version, operation, creditsUsed (1)
POST /videos/overlay
Request: videoId (required), text (required, 1-500), position? (top|center|bottom), fontSize? (8-200), topBottomMargin? (0-500), strokeThickness? (0-10)
Response 200 (EditResponse): videoId, url, version, operation, creditsUsed
Image Generation
POST /images/generate
Request: model (required: nano-banana-2 | google/nano-banana-edit), prompt (required, 1-20000), imageUrls? (required for edit, optional for text-to-image, max 14), aspectRatio? (nano-banana-2), imageSize? (nano-banana-edit), resolution? (1K|2K|4K), outputFormat? (png|jpeg|jpg), googleSearch? (boolean, nano-banana-2 only)
Response 201: imageId (img_xxx), model, status, creditsUsed, newBalance, estimatedCompletionTime, createdAt
GET /images/{imageId}
Response 200: imageId, status, model, prompt, url? (completed), imageSize?, resolution?, outputFormat?, creditsUsed, createdAt, completedAt?, failCode?, failMessage?
GET /images
Query: status?, limit? (1-100, default 20), page?
Response 200: images (ImageResponse[]), pagination (total, page, pageSize, hasMore)
Music Generation
POST /music/generate
Request: prompt (required, 1-2000), model? (V3_5|V4|V4_5|V4_5PLUS|V4_5ALL|V5, default V5), instrumental? (boolean, default true), title? (max 200), style? (max 500)
Response 201: musicId (mus_xxx), model, status, creditsUsed (3), newBalance, estimatedCompletionTime, createdAt
GET /music/{musicId}
Response 200: musicId, status, model, prompt, audioUrl? (completed), albumArtUrl?, duration?, title?, creditsUsed, createdAt, completedAt?, failCode?, failMessage?
GET /music
Query: status?, limit? (1-100, default 20), page?
Response 200: tracks (MusicResponse[]), pagination (total, page, pageSize, hasMore)
Upload
POST /upload
Request: multipart/form-data, field file. Accepted: video/mp4, video/quicktime, video/webm, image/png, image/jpeg, image/webp. Max 100MB.
Response 200: url (public URL for use in generation requests), contentType, size (bytes)
Characters
GET /characters
Response 200: characters (CharacterResponse[]), count, adminCount, userCount
GET /characters/{characterId}
CharacterResponse: _id, username, displayName, description, videoPreviewUrl?, type (admin|user), isActive, createdAt, updatedAt
Personas
GET /personas
Response 200: personas (PersonaResponse[]), count
POST /personas
Request: name (required, max 200), description (required, max 5000)
Response 201: { id }
GET /personas/{personaId}
Response 200: PersonaResponse
PATCH /personas/{personaId}
Request: name?, description?
DELETE /personas/{personaId}
PersonaResponse: _id, organizationId, name, description, createdAt, updatedAt
Messaging
GET /messaging
Response 200: messages (MessagingResponse[]), count
POST /messaging
Request: name (required, max 200), body (required, max 5000)
Response 201: { id }
GET /messaging/{messageId}
PATCH /messaging/{messageId}
Request: name?, body?
DELETE /messaging/{messageId}
MessagingResponse: _id, organizationId, name, body, createdAt, updatedAt
Products
GET /products
Response 200: products (ProductResponse[]), count
POST /products
Request: name (required, max 200), photos (required, URL[]), description? (max 1000), messaging? (max 5000)
Response 201: { id }
GET /products/{productId}
PATCH /products/{productId}
Request: name?, description?, photos?, messaging?
DELETE /products/{productId}
ProductResponse: _id, name, description, photos, messaging, createdAt, updatedAt
Styles
GET /styles
Query: type? (video|image)
Response 200: styles (StyleResponse[]), count
POST /styles
Request: name (required, max 200), description? (max 1000), type? (video|image), aspectRatio? (portrait|landscape|square), promptTemplate? (max 5000, placeholders: {productName}, {messaging}, {character})
Response 201: { id }
GET /styles/{styleId}
PATCH /styles/{styleId}
Request: name?, description?, aspectRatio?, promptTemplate?
DELETE /styles/{styleId}
StyleResponse: _id, name, description, type, aspectRatio, styleId, promptTemplate, isAdmin, isStandard
Social Accounts
GET /social/accounts
Response 200: accounts (SocialAccount[]), count
POST /social/accounts
Sync accounts from scheduling provider. Response 200: { success }
DELETE /social/accounts/{accountId}
Response 200: { success }
SocialAccount: accountId, platform (tiktok|instagram|youtube), username, displayName, profilePicture?, isActive
Social Posts
POST /social/posts
Request: videoUrl (required), accountIds (required, string[]), mode (required: schedule|draft|now), scheduledFor? (ms, required for schedule), timezone? (IANA, default UTC), content? (max 2200), videoId?, publishToInbox?, tiktokPrivacyLevel? (SELF_ONLY|PUBLIC_TO_EVERYONE|MUTUAL_FOLLOW_FRIENDS|FOLLOWER_OF_CREATOR), tiktokAllowComment?, tiktokAllowDuet?, tiktokAllowStitch?, tiktokCommercialContentType? (none|brand_organic|brand_content)
Response 201: SocialPost
GET /social/posts
Query: fromDate? (ms), toDate? (ms), includeDrafts? (boolean)
Response 200: posts (SocialPost[]), count
GET /social/posts/{postId}
PATCH /social/posts/{postId}
Request: content?, scheduledFor?, timezone?, accountIds? (at least one field)
DELETE /social/posts/{postId}
Response 200: { success }
POST /social/posts/{postId}/reschedule
Request: scheduledFor (required, ms), timezone?
POST /social/posts/{postId}/publish
Immediately publish a draft.
SocialPost: postId, platforms, status (draft|scheduled|published|failed), scheduledFor?, timezone, content, videoUrl, createdAt, publishedAt?
Viral Library
GET /viral-library/videos/{videoId}
Response 200: ViralLibraryVideo
ViralLibraryVideo: id, tiktokId, tiktokUrl, username, description, stats (views, likes, comments, shares, saves), hashtags, soundName, duration, thumbnailUrl, playUrl, analysis? (VideoAnalysis)
VideoAnalysis: hook, summary, whyItPerformed, attributesToCopy, hooksToTest, keyframes (array: timestamp, type, description, visual, audio, text), durationSeconds, tags, analyzedAt
GET /viral-library/search
Query: q (required, natural language), limit? (1-50, default 20)
Response 200: results (array of { video: ViralLibraryVideo, score: number }), query, total
Research
POST /scrape-tiktok
Request: query (required, max 500), mode? (keyword|hashtag|search, default keyword), limit? (1-10, default 10)
Response 200: scrapeId, count, videos (array: id, url, author, description, stats {views, likes, comments, shares}, duration, hashtags, thumbnail?, videoUrl?)
POST /content-plans
Request: scrapeId (required), brief (required, max 5000)
Response 200: planId, scrapeId, brief, topWins, gapsToTest, blueprints (array: category, strategy, evidence, contentIdeas [{hook, openingShot, contentOutline, cta}])
GET /content-plans
Response 200: plans (array: planId, scrapeId, brief, createdAt), count
POST /analyze-video
Request: videoUrl (required), prompt? (max 5000)
Response 200: summary, hook, keyframes (array: timestamp, type, description, visual, audio, text), durationSeconds, tags, whyItPerformed, attributesToCopy, hooksToTest
Error body (ApiError)
All error responses use RFC 7807: type, title, status, detail?, instance?, errors? (Record<string, string[]>)
Status codes: 400 validation, 401 auth, 402 insufficient credits, 403 insufficient scope, 404 not found, 429 rate limit, 500 server error.
Rate limit headers
All responses include: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset (unix timestamp seconds).
Common questions
How do I install Rawugc API in Cursor, Claude Code, or Codex?
Run npx skills add tfcbot/rawugc-skills --skill rawugc-api in the project where you want it, then ask your agent for the skill by name. The --skill flag installs only Rawugc API, not every skill in the repository.
Where does Rawugc API come from and what license is it under?
Rawugc API comes from the tfcbot/rawugc-skills repository on GitHub. That repository has 5 GitHub stars. The skill is published under the Apache-2.0 license.
Prefer plain text? Read the Rawugc API guide as markdown.