# Rumora docs # /docs/api/authentication --- title: Authenticate description: Send a workspace Bearer token and reuse an idempotency key on retry. --- Use the same token you mint on **API keys** for MCP. How to create it is in [Create an API key](/docs/using/agent-access). ## Headers Send this on every request: ```text Authorization: Bearer rmr_YOUR_TOKEN ``` Missing or revoked tokens return HTTP 401 with `"code": "UNAUTHORIZED"`. On `POST`, also send `idempotency_key` in the JSON body, at least 8 characters. You may send `Idempotency-Key` as a header instead. Reuse the same key on retry. MCP and REST share the key per workspace, so the same key will not spend twice. See [Idempotency](/docs/concepts/idempotency). ## First call to copy Replace the token, then run this. It spends nothing. ```bash export HOST=https://rumora.ai export TOKEN='rmr_YOUR_TOKEN' curl -sS "$HOST/api/v1/usage" \ -H "Authorization: Bearer $TOKEN" ``` You should see `credits_left`. Then post a comment: ```bash curl -sS -X POST "$HOST/api/v1/comments" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "video_url": "https://www.youtube.com/watch?v=VIDEO", "text": "Useful breakdown of this.", "idempotency_key": "comment-1" }' ``` Copy `id`, then poll `GET /api/v1/status/THREAD_ID`. When `identity` is present, like or reply with those fields. Live minimums are in the usage call. The full sequence is [First agent request](/docs/first-agent-request). # /docs/api/endpoints --- title: Endpoints description: REST paths map to the command reference. This page is an index, not a second contract. --- Each path is one command. Open the reference page for the body, the success JSON, and the errors. This table is only the map. | Method | Path | Command | | --- | --- | --- | | GET | `/api/v1/usage` | [get_usage](/docs/reference/get-usage) | | POST | `/api/v1/comments` | [post_comment](/docs/reference/post-comment) | | POST | `/api/v1/comments/like` | [like_comment](/docs/reference/like-comment) | | POST | `/api/v1/comments/reply` | [reply_to_comment](/docs/reference/reply-to-comment) | | POST | `/api/v1/threads` | [post_thread](/docs/reference/post-thread) | | POST | `/api/v1/finds` | [find_videos](/docs/reference/find-videos) | | GET | `/api/v1/status/:id` | [get_status](/docs/reference/get-status) | There is no paste route. Send `video_url` on `post_comment` instead. OpenAPI is at [OpenAPI](/docs/api/openapi). # /docs/api/errors --- title: Errors description: Program error codes, HTTP status, extra fields, and the next action. --- When a call fails, REST returns JSON of this shape. MCP tools return the same `code` values. HTTP status applies to REST only. ```json { "error": { "code": "UNAUTHORIZED", "message": "Missing or invalid Bearer token." } } ``` Extra fields may appear next to `code` and `message`: - `PAYMENT_REQUIRED` includes `checkout_url`, `credits_needed`, and `credits_have`. - `CONFLICT` includes `job_id`. - `QUANTITY` includes `min` and `max`. - `PARSE` on over-length text includes `max`. | Code | HTTP | When it happens | | --- | --- | --- | | `UNAUTHORIZED` | 401 | Missing, unknown, or revoked Bearer token | | `PAYMENT_REQUIRED` | 402 | Not enough credits | | `HELD` | 403 | Workspace is held | | `FORBIDDEN` | 403 | Find on a workspace without an active paid plan | | `OPTED_OUT` | 403 | The video owner opted out | | `NOT_FOUND` | 404 | Unknown route, thread, or job | | `CONFLICT` | 409 | A Find job is already open | | `RATE_LIMIT` | 429 | 10 write tools in the last 60 seconds | | `PARSE` | 400 | Body failed validation | | `QUANTITY` | 400 | Like quantity below min or above max | | `PLATFORM` | 400 | URL is not YouTube or TikTok | | `PROVIDER` | 400 | That action is not available, or Rumora could not complete it | ## Next Do this when you see the code. Symptom-first steps are in [Troubleshooting](/docs/troubleshooting). | Code | What you do | | --- | --- | | `UNAUTHORIZED` | Mint a key on **API keys**. Send `Authorization: Bearer rmr_...` with the full secret. | | `PAYMENT_REQUIRED` | Open `checkout_url`. Buy a plan or pack. Retry with the same `idempotency_key`. | | `HELD` | Contact support. Mutating commands stay blocked until the hold clears. | | `FORBIDDEN` | Start a paid plan, or paste a URL and post without Find. | | `OPTED_OUT` | Pick a different video. Existing live comments stay. | | `NOT_FOUND` | Check the path and copy `id` from the previous success JSON. | | `CONFLICT` | Poll `get_status` on `job_id`. Wait until that job finishes. | | `RATE_LIMIT` | Wait, then retry with the same `idempotency_key`. Reads are not counted. | | `PARSE` | Fix the field named in `message`. Call `get_usage` for live max length. | | `QUANTITY` | Send at least `min` from the error body. Rumora will not raise a low quantity. | | `PLATFORM` | Pass a YouTube watch or Shorts URL, or a TikTok video URL. | | `PROVIDER` | Call `get_usage`. If `canComment`, `canReply`, or `canLike` is false, that action is unavailable. | # /docs/api --- title: REST API description: HTTP routes for the same workspace commands as MCP. One token, one wallet, one idempotency map. --- The REST API is the same commands as MCP, over HTTP. There is no paste route and no second wallet. Base path is `/api/v1`. Authenticate with `Authorization: Bearer rmr_...`. Write requests send `idempotency_key` in JSON (or `Idempotency-Key` as a header). The key must be at least 8 characters. Paste a token and run the same routes in the browser. Mint the token and send Bearer plus an idempotency key. 10 write calls per workspace per minute. Error codes, HTTP status, and the next action. Generated spec from the command catalog. Bodies and responses are in [Command reference](/docs/reference). A full first job is [First agent request](/docs/first-agent-request). # /docs/api/openapi --- title: OpenAPI description: Machine-readable spec generated from the command catalog. --- Fetch the spec from the app when you want to generate a client or load the contract into an agent. It is built from the same catalog as the [command reference](/docs/reference). ```bash curl -sS "$HOST/api/v1/openapi" ``` Use the reference page for each command as the source of truth for field notes and example JSON. The spec does not replace [Errors](/docs/api/errors). # /docs/api/rate-limits --- title: Rate limits description: A workspace can run 10 write commands per minute. Reads are not counted. --- A workspace may run 10 writes in any 60 second window. A write over that cap returns `RATE_LIMIT` with HTTP 429. Two agents on the same team share the 10. The cap is per workspace, not per token. These kinds count as writes: `post_comment`, `like_comment`, `reply_to_comment`, `find_videos`, `post_thread`. `get_usage` and `get_status` do not count. Poll status as often as you need. ## What you should do on 429 Wait, then retry with the **same** `idempotency_key`. A new key after a 429 can double-spend if the first write actually landed. There is no documented burst product for a higher cap. If you need more throughput, space writes across minutes. # /docs/concepts/idempotency --- title: Idempotency description: Why write commands take a key, and how a retry finishes without a second charge. --- Every write needs `idempotency_key` of at least 8 characters. Send it as JSON `idempotency_key`, or as the `Idempotency-Key` header. MCP and REST share the key per workspace. The same key will not spend twice. ## What you should do 1. Pick a key per job, such as `comment-1` or `like-1`. Use a different key for a different job. 2. If the request times out, or you get `RATE_LIMIT` or `PAYMENT_REQUIRED` after you buy credits, send the **same** key again. 3. Do not generate a new key on retry. A new key is a new spend if the first write actually landed. `get_usage` and `get_status` have no key. They are reads. ## What the server does If a stored result already has an `id` and is not stuck in a pending crash window, the runner returns that result and does not run the command again. A key shorter than 8 characters is `PARSE`. That check exists so a client cannot accidentally mint a new spend on every retry. Do not reuse one key across different commands. The stored row is keyed by workspace plus key, and it records which command it belonged to. ## Crash windows, in plain language If the process dies after credits leave the wallet and before the comment is queued, a retry with the same key finishes the job instead of charging again. You do not need to handle that yourself. Send the same key. The like recipe that uses this correctly is [Comment then like](/docs/recipes/comment-then-like). # /docs/concepts/identity --- title: Comment identity description: Why likes use YouTube lc and TikTok username, and why replies never take an lc URL. --- Before you like or reply, poll `get_status` until `identity` is an object. Copy fields from that object. Do not invent YouTube ids you saw in the browser. Rumora agents post under their own accounts. They do not use your YouTube or TikTok login. After a comment is live, `get_status` returns the identity of the agent who posted it. Likes and replies must use those fields so the right comment gets the engagement. ## What you copy When the parent comment is live, `get_status` looks like this (shape, not a live id): ```json { "status": "live", "identity": { "platform": "youtube", "comment_id": "COMMENT_ID", "username": "posted_name", "video_url": "https://www.youtube.com/watch?v=VIDEO", "youtube_like_url": "https://www.youtube.com/watch?v=VIDEO&lc=COMMENT_ID" } } ``` | Next action | YouTube | TikTok | | --- | --- | --- | | Like | Send `url` as `youtube_like_url`, or `watch?v=` plus `lc=COMMENT_ID` | Send `video_url` plus `username` | | Reply | Send `video_url` plus `username`. Do not send `lc` | Send `video_url` plus `username` | `share_comment_id` and `cid` look like YouTube ids in a browser. They are not the identity Rumora returns. Sending them is a `PARSE` error. On TikTok, likes and replies both key off video URL plus the username of the agent who posted. If two comments on the same video share one username, Rumora cannot tell them apart. ## Why post_comment does not like A like needs a live comment id. `post_comment` returns while the line is still `queued`. There is nothing to like yet. A combined post-and-like body would spend like credits against an identity that does not exist. Like after `identity` is present. ## Why identity can be null `identity` stays `null` until the parent line is `live`. Keep polling `get_status`. The `next_step` string on that payload tells you which fields to send next. Treat that string as the instruction for the next call. The full like and reply recipes are [Comment then like](/docs/recipes/comment-then-like). # /docs/concepts --- title: Concepts description: Why credits, identity, status, and idempotency work this way. --- Read these when a walkthrough tells you to wait for `identity`, reuse a key, or check the team wallet, and you want the rule in one place. Each page starts with what you should do, then explains why. Credits sit on the team. Agents spend that same balance. What to copy from get_status before you like or reply. When to stop polling a thread or a Find job. Why retries must send the same key, or you can be charged twice. # /docs/concepts/status-and-polling --- title: Status and polling description: How thread and Find handles move from queued to live, and what get_status returns. --- Every write returns a handle before the comment is live. `post_comment` and `post_thread` return a thread id. `find_videos` returns a Find job id. `get_status` accepts either id. There is no webhook. You poll. ```bash curl -sS "$HOST/api/v1/status/ID_FROM_THE_LAST_CALL" \ -H "Authorization: Bearer $TOKEN" ``` Reads do not count toward the 10 writes per minute limit. Wait a few seconds between polls. ## When to stop (thread) The JSON has `"type": "thread"`. - Keep polling while `identity` is `null` or `status` is not `live`. - Stop when `identity` is an object. Then like or reply with those fields. See [Comment identity](/docs/concepts/identity). - If `status` is a failure, stop and read `error`. Do not like. `next_step` is a sentence telling you the next call. Follow it. ## When to stop (Find) The JSON has `"type": "find"`. - Keep polling while `cards` is missing or empty and `status` is not `refunded`. - Stop when `cards` has URLs. Copy a `url`, then call `post_comment` or `post_thread`. Find does not paste and does not post. - Stop when `"status": "refunded"`. The search returned nothing and the Find credits came back. Change keywords and start a new job with a new `idempotency_key`. ## How often Poll every few seconds. Most comments go live in well under a minute. If identity never appears, open **Threads** in the web app and look up the same id. # /docs/concepts/workspace-and-credits --- title: Workspace and credits description: Credits sit on the team workspace. MCP and REST do not open a second balance. --- Credits live on the **team** you have open, not on your personal login. A comment you post in the browser spends the same pool as `post_comment` from an agent. That is why keys are minted on the team **API keys** page, and why a personal account has no key page. ## What you should do 1. Open the team you intend to spend from before you paste a URL or create a token. 2. Read the credits chip in the header, or call `get_usage` and read `credits_left`. 3. Before a write, also read `comment_credits`, `like_credits`, `find_credits`, and the `limits` for the platform you will use. Those limits are not prices. They are live max length and like minimums, and they can change. ## What spends credits | Action | What to read on `get_usage` | Typical value today | | --- | --- | --- | | One comment or one reply | `comment_credits` | 25 | | One like | `like_credits` times `quantity` | 1 per like | | One Find keyword | `find_credits` | 50 | Trust `get_usage` and the composer over any number on this page. Those limits can change. Credits leave the wallet when the write is **accepted**, before the comment is live. Retrying with the same `idempotency_key` does not take a second charge. An empty Find job refunds the Find credits the same way the web app refunds. ## Plans, packs, and Find Monthly plans grant a pool. Add-on packs add credits on top. When a write fails with `PAYMENT_REQUIRED`, the error includes `checkout_url` for that team's **Billing** page. `find_enabled` is true only while the team has an active paid plan. A free grant can still paste a URL and post. ## Holds If the workspace is held, writes return `HELD`. Find and Post stay paused until support clears the hold. `get_usage` and `get_status` still work. How to buy more is in [Buy a plan](/docs/using/billing). # /docs/first-agent-request --- title: First agent request description: Mint a token, read usage, post a comment, poll until identity is present, then like. icon: Bot --- When you finish this page, an agent or a terminal has posted one comment on YouTube or TikTok and started liking that comment, using the same credits as the web app. MCP tools send the same JSON as the curl bodies below. If you would rather click than use a terminal, paste the token into the [playground](/docs/playground) and run each command there in the same order. ## Before you start You need a **team** workspace with credits, and a video URL. Home paste in the web app accepts YouTube Shorts and TikTok only. This HTTP command also accepts a regular YouTube watch URL. Set these once. `HOST` is `https://rumora.ai` in production. `TOKEN` is filled in after you create the key. ```bash export HOST=https://rumora.ai export TOKEN='rmr_YOUR_TOKEN' ``` ## 1. Create a key 1. Sign in and open the team workspace. 2. Click **API keys** in the sidebar. 3. Click **Create key**. 4. Copy the full secret. It starts with `rmr_`. Reload hides it. Put it in the shell: ```bash export TOKEN='rmr_PASTE_THE_SECRET_HERE' ``` Only members who can manage settings can create a key. Personal accounts have no API keys page. More client snippets are in [Sideload the MCP server](/docs/mcp/sideload). ## 2. Read remaining credits and live limits This call spends nothing. Always do it before a write, because max comment length and minimum likes can change. ```bash curl -sS "$HOST/api/v1/usage" \ -H "Authorization: Bearer $TOKEN" ``` You should see `credits_left`, `comment_credits`, `like_credits`, `find_credits`, and `limits` for `youtube` and `tiktok`. Copy two numbers for the platform of your video: - `commentMaxLength` is the longest text you may send in the next step. - `likeMin` is the smallest like `quantity` you may send in the last step. If you see `"code": "UNAUTHORIZED"`, the token is wrong. Create the key again and export `TOKEN` with the full secret, not the prefix. ## 3. Post one comment Replace `VIDEO_URL` with the real URL. Replace `text` with your comment, at or under `commentMaxLength`. Keep `idempotency_key` at least 8 characters. If curl times out, send the **same** key again. Do not add `likes`. The comment is not live yet, so there is nothing to like. ```bash curl -sS -X POST "$HOST/api/v1/comments" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "video_url": "VIDEO_URL", "text": "Useful breakdown of this.", "idempotency_key": "comment-1" }' ``` You should see `"type": "thread"` and `"status": "queued"`. Copy `id`. That is the thread id. If you see `"code": "PAYMENT_REQUIRED"`, open `checkout_url` from the error, buy credits, then retry with `comment-1`. If you see `"code": "PLATFORM"`, the URL is not YouTube or TikTok. ## 4. Poll until identity is present Replace `THREAD_ID` with the `id` from step 3. Run this, wait a few seconds, run it again. Stop when `identity` is an object, not `null`. ```bash curl -sS "$HOST/api/v1/status/THREAD_ID" \ -H "Authorization: Bearer $TOKEN" ``` What you copy from `identity` depends on the platform: - **YouTube likes** need `youtube_like_url`, or the watch URL plus `lc=` and `comment_id`. - **TikTok likes** need `video_url` and `username`. - **Replies on both platforms** use the video URL plus the posted username. Do not send an `lc` URL on a reply. If `identity` stays `null`, keep polling. The comment is not live yet. This is explained in [Comment identity](/docs/concepts/identity). ## 5. Like the live comment Set `quantity` to `likeMin` from step 2, or higher. Use a **new** idempotency key (`like-1`, not `comment-1`). Replace the identity values with what you copied. **YouTube** ```bash curl -sS -X POST "$HOST/api/v1/comments/like" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "url": "https://www.youtube.com/watch?v=VIDEO&lc=COMMENT_ID", "quantity": 25, "idempotency_key": "like-1" }' ``` **TikTok** ```bash curl -sS -X POST "$HOST/api/v1/comments/like" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "video_url": "https://www.tiktok.com/@user/video/VIDEO", "username": "posted_name", "quantity": 25, "idempotency_key": "like-1" }' ``` You should see `"type": "like"` and `"status": "queued"`. If you see `"code": "QUANTITY"`, send at least `min` from the error body. ## If a call fails Match `error.code` in [Errors](/docs/api/errors). The same sequence without curl is in [Comment then like](/docs/recipes/comment-then-like). # /docs/getting-started --- title: Get started description: Sign in, open a team workspace, and post a first comment from the web app. icon: Rocket --- When you finish this page, you will have signed in, added a video to a team workspace, and posted one comment from the Rumora web app. The thread will show up under **Threads** when it is live. This is the browser path. The same job over HTTP is [First agent request](/docs/first-agent-request). ## Open a team workspace 1. Go to [rumora.ai](/) and sign in. 2. Open a **team** workspace, not a personal account. Credits live on the team. If you only have a personal account, create or join a team first. 3. Look at the credits count in the header. If it is 0, open **Billing**, buy a plan, then come back. You should see **Home** with a **Paste URL** field. ## Paste a video 1. On **Home**, if **Search** is selected, click **Paste URL**. 2. Paste a **YouTube Shorts** URL or a **TikTok** video URL. You can paste more than one line. 3. Click **Continue**. You should see the video on **Home**. Click it to open the composer. The field says **Free to add. YouTube Shorts and TikTok only.** A regular `youtube.com/watch?v=` URL fails here. Channels, playlists, and Instagram links fail here. An agent can still pass a watch URL to `post_comment`. If you do not have a Shorts or TikTok URL, run [Find](/docs/using/find) on a paid plan and pick a card. Paste does not spend credits. Posting the comment will. ## Write the comment and post 1. If **Generate** is disabled, fill **Product name**, **What it is**, and **Why it is better** on **Home**, then open the video again. 2. Type the parent comment, or click **Generate** and edit the draft until it is something you would post yourself. 3. Stay under the live max length shown in the composer. That number comes from the same source as `get_usage`. 4. Add replies only if you already wrote them. Rumora does not invent a thread of replies for you. 5. If you want likes in the same submit, click **Add likes** and set the quantity at or above the minimum shown. Rumora will not raise a number you set too low. 6. Click **Post**. Credits leave the workspace at submit, before the comment is live. You should see the thread move from writing toward live. If you leave the video, open **Threads** and find the same item. ## Next - [Comments, replies, and likes](/docs/using/comments) is the rest of the composer. - [First agent request](/docs/first-agent-request) does this job with curl. - [Sideload the MCP server](/docs/mcp/sideload) connects Cursor or Claude Code to the same wallet. # /docs/ --- title: Overview description: Use Rumora in the browser, connect an agent with MCP, or call the same commands over HTTP. icon: House --- Rumora agents post comments, send replies, and like comments on YouTube and TikTok from a **team** workspace. Credits come from that team. An agent does not get a second wallet. Pick the path that matches how you want to work. Each of these pages is a walkthrough you can follow without assembling steps from somewhere else. Sign in, paste a video, and post a first comment in the web app. Mint a token, then post, poll, and like with copy-paste curl. Finished jobs: comment then like, find then comment, post a thread, rotate a token. One page per command, with the JSON MCP and REST both use. ## Which path to open If you work in the browser, start with [Get started](/docs/getting-started). The click-by-click pages are under [Using Rumora](/docs/using). If you connect Cursor, Claude Code, or another MCP client, start with [Sideload the MCP server](/docs/mcp/sideload), then run [First agent request](/docs/first-agent-request) so you see a real post. If you write HTTP, start with [Authenticate](/docs/api/authentication). The machine-readable spec is [OpenAPI](/docs/api/openapi). ## What stays the same on every path MCP and REST share one command runner, one credit balance, and one idempotency map per workspace. A key you mint on **API keys** works for both. Before you like or reply, wait until `get_status` returns `identity`. YouTube likes use an `lc=` comment URL. Replies on both platforms use the video URL plus the posted username. That rule is in [Comment identity](/docs/concepts/identity). Copy this page as Markdown from the Open menu, or fetch [/llms.txt](/llms.txt) for an index and [/llms-full.txt](/llms-full.txt) for the full text. # /docs/mcp --- title: MCP description: Connect an agent to a Rumora workspace. The agent spends the same credits as the web app. --- Rumora exposes an MCP server at `/api/mcp`. You add it to Cursor, Claude Code, or another MCP client. It is not listed in a public directory. The agent authenticates with a Bearer token you mint on **API keys**. That token also works on the [REST API](/docs/api). Commands share one runner, one wallet, and one idempotency map per workspace. Do this in order: Mint a token and paste the JSON into Cursor, Claude Code, or a generic client. Call get_usage first, then post, poll, and like with identity. Tool names that map to the command reference. A full copy-paste job after the server is connected is [First agent request](/docs/first-agent-request). # /docs/mcp/sideload --- title: Sideload the MCP server description: Mint a workspace token and add Rumora to Cursor, Claude Code, or another MCP client. icon: Plug --- When you finish this page, Cursor, Claude Code, or another MCP client can call Rumora tools against your team workspace. A team owner, or anyone who can manage settings, mints the key. Personal accounts do not have this page. ## Create a key 1. Sign in and open the **team** workspace in Rumora. 2. Click **API keys** in the sidebar. 3. Click **Create key**. 4. Copy the full secret immediately. It starts with `rmr_`. Reload hides it and leaves only the prefix. 5. To rotate later, follow [Rotate a token](/docs/recipes/rotate-a-token). ## Add the server Replace `rmr_YOUR_TOKEN` with the secret from the last step. The URL below is production. If the **MCP** page in the app shows a different origin, use that origin instead. The path is always `/api/mcp`. Open Cursor MCP settings and paste this object. Reload MCP after you save. ```json { "mcpServers": { "rumora": { "url": "https://rumora.ai/api/mcp", "headers": { "Authorization": "Bearer rmr_YOUR_TOKEN" } } } } ``` Run this, then restart the session so the client loads the server. ```bash claude mcp add --transport http rumora https://rumora.ai/api/mcp \ --header "Authorization: Bearer rmr_YOUR_TOKEN" ``` Any client that speaks Streamable HTTP can use this object. The header name is `Authorization`. The value is `Bearer` plus the secret. ```json { "url": "https://rumora.ai/api/mcp", "headers": { "Authorization": "Bearer rmr_YOUR_TOKEN" } } ``` GET `/api/mcp` returns 405. The client must use the MCP POST transport. ## Confirm it loaded Ask the agent to call `get_usage`. You should see `credits_left`. If you see unauthorized, the header still has the placeholder or the prefix instead of the full secret. Then follow [Recommended workflow](/docs/mcp/workflow), or run [First agent request](/docs/first-agent-request) with curl to see the same JSON. # /docs/mcp/tools --- title: MCP tools description: Tool names map to the command reference. MCP and REST share one runner. --- Each tool is one command. Copy the name into the agent, then open the reference page for the arguments and the JSON you should see back. There is no second field list on this page, so it cannot drift from the runner. Call `get_usage` first. The order is in [Recommended workflow](/docs/mcp/workflow). | Tool | What it does | REST | Reference | | --- | --- | --- | --- | | `get_usage` | Remaining credits and live limits. Spends nothing. | `GET /api/v1/usage` | [get_usage](/docs/reference/get-usage) | | `post_comment` | Post one top-level comment. Does not like. | `POST /api/v1/comments` | [post_comment](/docs/reference/post-comment) | | `get_status` | Poll a thread id or a Find job id. | `GET /api/v1/status/:id` | [get_status](/docs/reference/get-status) | | `like_comment` | Like a live comment using identity from `get_status`. | `POST /api/v1/comments/like` | [like_comment](/docs/reference/like-comment) | | `reply_to_comment` | Reply using the video URL plus the parent username. | `POST /api/v1/comments/reply` | [reply_to_comment](/docs/reference/reply-to-comment) | | `find_videos` | Start a paid Find job. Returns a job id, not cards. | `POST /api/v1/finds` | [find_videos](/docs/reference/find-videos) | | `post_thread` | Parent plus replies you wrote. No likes field. | `POST /api/v1/threads` | [post_thread](/docs/reference/post-thread) | # /docs/mcp/workflow --- title: Recommended workflow description: Tool order for an agent that spends workspace credits without double-charging or guessing identity. --- When you finish this page, the agent has read usage, posted a comment, waited until it is live, and liked or replied with the identity Rumora returned. Paste the JSON into the matching MCP tool. Curl for the same job is in [First agent request](/docs/first-agent-request). Do not skip `get_usage`. Do not send `likes` on `post_comment`. Do not like until `identity` is an object. ## Read usage first Call `get_usage` with an empty arguments object. ```json {} ``` Copy `credits_left`, `commentMaxLength`, `likeMin`, and `find_enabled`. If `credits_left` is too low, stop and tell the user to open **Billing**. ## Get a video URL If the user already gave you a YouTube or TikTok URL, use it. If they did not, and `find_enabled` is true, call `find_videos`: ```json { "platform": "youtube", "terms": ["ai coding agents"], "idempotency_key": "find-1" } ``` Copy `id`. Call `get_status` with that id until `cards` has URLs, then pick one `url`. If you get `CONFLICT`, poll `job_id` from the error instead of starting a second search. ## Post the comment Call `post_comment`. Keep `text` at or under `commentMaxLength`. Keep `idempotency_key` at least 8 characters. Reuse it if the tool times out. Do not add `likes`. ```json { "video_url": "VIDEO_URL", "text": "Useful breakdown of this.", "idempotency_key": "comment-1" } ``` Copy `id`. That is the thread id. ## Poll until identity is present Call `get_status` with the thread id. Wait a few seconds and call it again until `identity` is an object, not `null`. Reads do not count toward the write rate limit. ```json { "id": "THREAD_ID" } ``` On YouTube, copy `youtube_like_url` (or `comment_id`). On TikTok, copy `video_url` and `username`. For a reply on either platform, copy `video_url` and `username`. ## Like or reply Use a **new** idempotency key. Set like `quantity` to `likeMin` or higher. **YouTube like** ```json { "url": "https://www.youtube.com/watch?v=VIDEO&lc=COMMENT_ID", "quantity": 25, "idempotency_key": "like-1" } ``` **TikTok like** ```json { "video_url": "https://www.tiktok.com/@user/video/VIDEO", "username": "posted_name", "quantity": 25, "idempotency_key": "like-1" } ``` **Reply (both platforms)** ```json { "video_url": "VIDEO_URL", "username": "posted_name", "text": "Agree on the pricing point.", "idempotency_key": "reply-1" } ``` Do not send `lc` on reply. Do not send `cid` or `share_comment_id`. If a write fails, read `code` and follow [Errors](/docs/api/errors). If the workspace is held, stop. Field lists are in [Command reference](/docs/reference). # /docs/playground --- title: Playground description: Paste a workspace token and run the same REST commands the docs describe. icon: Terminal --- Use this page when you want to try a command without opening a terminal. Paste the `rmr_` secret from **API keys**, pick a command, fill the fields, then click **Run**. The JSON on the right is the live response from your workspace. Start with **get_usage** so you see remaining credits and live limits before a write. Writes spend the same credits as the web app. Check **Spend workspace credits** before those commands will run. # /docs/recipes/comment-then-like --- title: Comment then like description: Post one comment, wait until it is live, then like it with the identity Rumora returns. --- When you finish this page, one comment is live on a YouTube or TikTok video and agents have started liking that same comment. You already have the video URL. If you do not, use [Find then comment](/docs/recipes/find-then-comment) first. ## Before you start You need all of this: 1. A **team** workspace with enough credits for one comment plus the likes you will send. Today a comment is 25 credits and each like is 1 credit. Trust `get_usage` for the live numbers. 2. An API key that starts with `rmr_`. Create one on **API keys** in the team sidebar. Copy the secret the moment it appears. A reload hides it. 3. A video URL. YouTube watch and Shorts URLs both work here. TikTok video URLs work here. Instagram does not. Set these once in your terminal. `HOST` is `https://rumora.ai` in production. `TOKEN` is the secret you copied, still including `rmr_`. ```bash export HOST=https://rumora.ai export TOKEN='rmr_YOUR_TOKEN' ``` You can paste the same token into the [playground](/docs/playground) and run the commands there instead of curl. ## 1. Read live limits This call spends nothing. It tells you how long the comment may be and the smallest like quantity Rumora will accept. ```bash curl -sS "$HOST/api/v1/usage" \ -H "Authorization: Bearer $TOKEN" ``` You should see JSON with `credits_left` and a `limits` object that has `youtube` and `tiktok`. Open the platform you will post on and copy two numbers: - `commentMaxLength` is the longest comment you may send. - `likeMin` is the smallest `quantity` you may send later. If you send less, the like call fails. Rumora will not raise the number for you. If you see `"code": "UNAUTHORIZED"`, the token is missing, truncated, or revoked. Create a new key and export `TOKEN` again. ## 2. Post the comment Replace `VIDEO_URL` with the real video URL. Replace the `text` value with your comment, and keep it at or under `commentMaxLength`. Keep `idempotency_key` at least 8 characters. If this request times out, send the **same** key again so you are not charged twice. Do not add a `likes` field. A like needs a live comment id, and the comment is not live yet. ```bash curl -sS -X POST "$HOST/api/v1/comments" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "video_url": "VIDEO_URL", "text": "Useful breakdown of this.", "idempotency_key": "comment-1" }' ``` You should see `"type": "thread"` and `"status": "queued"`. Copy `id`. That value is the thread id you poll next. Credits have already left the wallet. If you see `"code": "PAYMENT_REQUIRED"`, open `checkout_url` from the error, buy credits, then retry with the same `idempotency_key`. If you see `"code": "OPTED_OUT"`, that creator blocked Rumora. Pick a different video. ## 3. Wait until the comment is live Replace `THREAD_ID` with the `id` from step 2. Run this, wait a few seconds, and run it again until `identity` is an object instead of `null`. Reads do not count toward the write rate limit. ```bash curl -sS "$HOST/api/v1/status/THREAD_ID" \ -H "Authorization: Bearer $TOKEN" ``` Stop when `"status"` is `"live"` and `identity` has fields inside it. - On **YouTube**, copy `youtube_like_url`. If that key is missing, copy `comment_id` and build `https://www.youtube.com/watch?v=VIDEO&lc=COMMENT_ID` yourself from the video URL plus `comment_id`. - On **TikTok**, copy `video_url` and `username`. You will send those two fields on the like call. If `identity` stays `null`, the comment is not live yet. Keep polling. If it never lands, open **Threads** in the web app and look up the same id. ## 4. Like the live comment Set `quantity` to `likeMin` from step 1, or higher, not lower. Replace the identity fields with the values you copied in step 3. Use a **new** idempotency key for the like. Do not reuse `comment-1`. **YouTube** ```bash curl -sS -X POST "$HOST/api/v1/comments/like" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "url": "https://www.youtube.com/watch?v=VIDEO&lc=COMMENT_ID", "quantity": 25, "idempotency_key": "like-1" }' ``` **TikTok** ```bash curl -sS -X POST "$HOST/api/v1/comments/like" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "video_url": "https://www.tiktok.com/@user/video/VIDEO", "username": "posted_name", "quantity": 25, "idempotency_key": "like-1" }' ``` You should see `"type": "like"` and `"status": "queued"`. Likes are in progress. Poll `get_status` on the original thread id if you want to watch them finish. If you see `"code": "QUANTITY"`, the error body includes `min`. Send at least that number. ## 5. Reply (optional) Replies use the video URL plus `identity.username` on both platforms. Do not send `lc=`. Use a new idempotency key. ```bash curl -sS -X POST "$HOST/api/v1/comments/reply" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "video_url": "VIDEO_URL", "username": "posted_name", "text": "Agree on the pricing point.", "idempotency_key": "reply-1" }' ``` You should see `"type": "reply"` and `"status": "queued"`. ## If something fails Match `error.code` in [Errors](/docs/api/errors). The reason likes cannot share a body with `post_comment` is in [Comment identity](/docs/concepts/identity). # /docs/recipes/find-then-comment --- title: Find then comment description: Start a Find job on a paid plan, pick a video URL from the cards, then post a comment. --- When you finish this page, Rumora has searched YouTube or TikTok for you, you have picked one video from the result cards, and a comment is queued on that video. Find does not paste the video and does not post the comment. Those are separate steps on purpose, so you choose the URL. ## Before you start You need all of this: 1. A **team** workspace on an **active paid plan**. Find is off on a free grant. `get_usage` must show `"find_enabled": true`. 2. Enough credits for the search plus the comment. Today each keyword is 50 credits and a comment is 25 credits. Trust `get_usage` for `find_credits` and `comment_credits`. 3. An API key that starts with `rmr_`, copied from **API keys**. 4. One to ten search keywords. You will type them. Rumora does not invent them unless you use **Get inspired** in the web app. Set these once: ```bash export HOST=https://rumora.ai export TOKEN='rmr_YOUR_TOKEN' ``` You can run the same commands in the [playground](/docs/playground). ## 1. Confirm Find is allowed ```bash curl -sS "$HOST/api/v1/usage" \ -H "Authorization: Bearer $TOKEN" ``` Check three things in the JSON: - `find_enabled` is `true`. If it is `false`, open **Billing**, start a paid plan, then run this call again. - `credits_left` is at least `find_credits` times the number of keywords you will send, plus `comment_credits` for the post. - `limits.youtube.commentMaxLength` or `limits.tiktok.commentMaxLength`, matching the platform you will search. If you see `"code": "UNAUTHORIZED"`, mint a new key. ## 2. Start the search `platform` must be `youtube` or `tiktok`. `terms` is an array of keywords. Each keyword spends `find_credits`. Keep `idempotency_key` at least 8 characters and reuse it if this request times out. ```bash curl -sS -X POST "$HOST/api/v1/finds" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "platform": "youtube", "terms": ["ai coding agents"], "idempotency_key": "find-1" }' ``` You should see `"type": "find"` and `"status": "queued"`. Copy `id`. That is the Find job id. If you see `"code": "FORBIDDEN"`, the workspace has no paid plan. [Buy a plan](/docs/using/billing) or [paste a URL](/docs/using/paste) instead. If you see `"code": "CONFLICT"`, a Find job is already running for this workspace. Copy `job_id` from the error body and poll that id in step 3. Do not start a second search. If you see `"code": "PAYMENT_REQUIRED"`, open `checkout_url`, buy credits, then retry with the same `idempotency_key`. ## 3. Poll until cards appear Replace `JOB_ID` with the `id` from step 2, or with `job_id` from a `CONFLICT` error. Run this every few seconds. ```bash curl -sS "$HOST/api/v1/status/JOB_ID" \ -H "Authorization: Bearer $TOKEN" ``` Watch `status` and `cards`: - When `cards` is a non-empty array, you are done polling. Each card has a `url`. Copy the `url` you want to comment on. - When `"status": "refunded"`, the search returned nothing and the Find credits came back. Change the keywords and start again with a **new** idempotency key. - When `"status": "queued"` or another in-progress value, wait and poll again. Find still has not posted a comment. ## 4. Post a comment on the URL you picked Replace `VIDEO_URL` with a `url` from `cards`. Keep `text` at or under `commentMaxLength` from step 1. Use a **new** idempotency key. Do not send `likes`. ```bash curl -sS -X POST "$HOST/api/v1/comments" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "video_url": "VIDEO_URL", "text": "Useful breakdown of this.", "idempotency_key": "comment-1" }' ``` You should see `"type": "thread"` and `"status": "queued"`. Copy `id` if you will like or reply next. To like that comment after it is live, continue with [Comment then like](/docs/recipes/comment-then-like) from the poll step, using this new thread id. ## If something fails Match `error.code` in [Errors](/docs/api/errors). Why Find is a job you poll, not a list of URLs in the first response, is in [Status and polling](/docs/concepts/status-and-polling). # /docs/recipes --- title: Recipes description: Finished jobs you can copy. Each page is the full sequence, including what you should see after every call. --- A recipe is one job from start to finish. You copy the commands, replace the placeholders, and stop when the last step shows the JSON it describes. You do not need to assemble the sequence from the reference pages. If you have never minted a key, do [First agent request](/docs/first-agent-request) once. That page is the same style as these recipes, with extra detail on creating the token. You have a video URL. Post a comment, wait until it is live, then like it. You do not have a URL yet. Search, pick a video from the cards, then post. You already wrote a parent comment and at least one reply. Send them together. A secret leaked. Revoke it and mint a new one so agents can connect again. MCP tools take the same JSON as the curl bodies on these pages. Field lists live in [Command reference](/docs/reference) if a call fails and you need the exact name of a field. # /docs/recipes/post-a-thread --- title: Post a thread description: Send a parent comment plus replies you already wrote, then like live lines if you want likes. --- When you finish this page, Rumora has queued one parent comment and at least one reply on the same video. You wrote every line. Rumora will not generate replies for you. ## Before you start You need all of this: 1. A **team** workspace with enough credits. Each line (parent and every reply) costs `comment_credits` from `get_usage`. Today that is 25 per line, so a parent plus one reply is 50. 2. An API key that starts with `rmr_`, copied from **API keys**. 3. A YouTube or TikTok video URL. 4. The parent text, and at least one reply text, already written. Set these once: ```bash export HOST=https://rumora.ai export TOKEN='rmr_YOUR_TOKEN' ``` You can run the same commands in the [playground](/docs/playground). ## 1. Read live max length ```bash curl -sS "$HOST/api/v1/usage" \ -H "Authorization: Bearer $TOKEN" ``` Open `limits` for the platform of your URL. Every line you send must fit `commentMaxLength` for the parent and `replyMaxLength` for each reply. If `credits_left` is below `comment_credits` times the number of lines, buy credits first. ## 2. Send the parent and the replies Replace `VIDEO_URL`, `parent`, and each reply `content`. `replies` must have at least one object. You may send at most 12 replies. `wait_hours` is optional. It is how many hours Rumora waits after Post before sending that reply. Each reply allows 0 to 12. The sum across replies cannot exceed 48. Replies never send before the parent is live, even if `wait_hours` is 0. Do not add a `likes` field. Like live lines later with `like_comment`. ```bash curl -sS -X POST "$HOST/api/v1/threads" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "video_url": "VIDEO_URL", "parent": "The pricing section is the part that matters.", "replies": [ { "content": "The demo at 3:12 is the same claim.", "wait_hours": 2 } ], "idempotency_key": "thread-1" }' ``` You should see `"type": "thread"`, `"status": "queued"`, and `line_count` matching parent plus replies. Copy `id`. Credits for every line have already left the wallet. If you see `"code": "PARSE"`, read `message`. Common causes are an empty `parent`, empty `replies`, a reply without `content`, or text over the live max length. ## 3. Wait until the parent is live Replace `THREAD_ID` with the `id` from step 2. Poll until `identity` is an object. ```bash curl -sS "$HOST/api/v1/status/THREAD_ID" \ -H "Authorization: Bearer $TOKEN" ``` Replies dispatch after this parent is live. You do not send the replies again. ## 4. Like a live line (optional) If you want likes on the parent, use [Comment then like](/docs/recipes/comment-then-like) from the like step, with this thread's `identity`. Set `quantity` to `likeMin` or higher from step 1. ## If something fails Match `error.code` in [Errors](/docs/api/errors). The field list is in [post_thread](/docs/reference/post-thread). # /docs/recipes/rotate-a-token --- title: Rotate a token description: Revoke a leaked workspace token and mint a new one so agents can connect again. --- When you finish this page, the old `rmr_` secret no longer works and every agent uses a new secret. There is one active token per workspace. Revoke is immediate. ## When to do this Do this if the secret was pasted into a ticket, a chat, a screenshot, or a git commit. Treat that string as public. Do not keep using it. ## 1. Open the key page 1. Sign in at [rumora.ai](/). 2. Open the **team** workspace that minted the leaked key. Personal accounts have no API keys page. 3. Click **API keys** in the sidebar. You should see the current key prefix, which looks like `rmr_` plus a few characters. That prefix is not enough to authenticate. The full secret is only shown at create time. ## 2. Revoke the leaked key Click **Revoke key**. Confirm if the page asks you to. From this moment, any client that still sends the old secret gets HTTP 401 with `"code": "UNAUTHORIZED"`. That is the expected result. It means the leak can no longer spend credits. ## 3. Create a new key 1. Click **Create key**. 2. Copy the full secret immediately. It starts with `rmr_` and is long. A reload hides it and leaves only the prefix. Store it in your password manager or in the agent's secret store. Do not commit it. ## 4. Put the new secret in every client Do every place that had the old secret: - **Cursor**: open MCP settings, replace `rmr_YOUR_TOKEN` in the Rumora server `Authorization` header, then reload MCP. - **Claude Code**: run the add command again with the new secret. Restart the session. - **Scripts and curl**: export a new `TOKEN`, or edit the `Authorization` header. - **Playground**: paste the new secret into the Authorization field. It is stored in this browser tab only. The JSON to paste into Cursor is in [Sideload the MCP server](/docs/mcp/sideload). ## 5. Confirm the new key works ```bash export HOST=https://rumora.ai export TOKEN='rmr_YOUR_NEW_TOKEN' curl -sS "$HOST/api/v1/usage" \ -H "Authorization: Bearer $TOKEN" ``` You should see `credits_left`. If you still see `"code": "UNAUTHORIZED"`, you pasted the prefix instead of the full secret, or the client is still sending the old header. Create the key again and replace the secret in the client. ## If something fails Only members who can manage settings can create or revoke a key. Everyone else can see the prefix. If you cannot click **Create key**, ask a workspace owner. # /docs/reference/find-videos --- title: find_videos description: Search for rising videos. Paid plan only. Returns a job handle. Does not paste or post. --- The MCP tool name is `find_videos`. HTTP is `POST /api/v1/finds` with `Authorization: Bearer rmr_...`. Starts a paid search and returns a job id. It does not paste a video and does not post. Poll `get_status` on `id` until `cards` has URLs, then pick one and call `post_comment`. 50 credits per keyword. Empty finds refund the same amount as the web app. Call get_usage first and read the live number. ## Request Set `HOST` to `https://rumora.ai` in production. Replace `rmr_YOUR_TOKEN` with the full secret from **API keys**. Keep `idempotency_key` at least 8 characters and reuse it if this request times out. ```bash curl -sS -X POST "$HOST/api/v1/finds" \ -H "Authorization: Bearer rmr_YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "platform": "youtube", "terms": [ "ai coding agents" ], "idempotency_key": "find-1" }' ``` You should see JSON that includes `id`, `type`, `status`, `credits_charged`, `next_step`. If you see `"error"`, match `code` in [Errors](/docs/api/errors). ## Response ```json { "id": "JOB_ID", "type": "find", "status": "queued", "credits_charged": 50, "next_step": "Poll get_status until cards appear or the job fails. Empty finds refund the same credits as the web app." } ``` ## Errors - [`UNAUTHORIZED`](/docs/api/errors): Mint a key on API keys. Send Authorization: Bearer rmr_... - [`PARSE`](/docs/api/errors): Fix the field named in message. Call get_usage for live max length. - [`FORBIDDEN`](/docs/api/errors): Open Billing and start a paid plan, or paste a URL and post without Find. - [`PAYMENT_REQUIRED`](/docs/api/errors): Open checkout_url from the error body. Buy a plan or an add-on pack, then retry with the same idempotency_key. - [`HELD`](/docs/api/errors): Contact support. Mutating commands stay blocked until the hold clears. - [`CONFLICT`](/docs/api/errors): Poll get_status on the job_id in the error body. Wait until that job finishes. - [`RATE_LIMIT`](/docs/api/errors): Wait, then retry with the same idempotency_key. Reads are not counted. The JSON error envelope is documented in [Errors](/docs/api/errors). ## Credits 50 credits per keyword. Empty finds refund the same amount as the web app. ## Next Poll get_status on id until cards appear. A second open Find job returns CONFLICT with job_id. Poll that id instead of starting another search. A full copy-paste job that uses this command is in [Recipes](/docs/recipes). Identity and polling are explained in [Comment identity](/docs/concepts/identity) and [Status and polling](/docs/concepts/status-and-polling). # /docs/reference/get-status --- title: get_status description: Poll a thread id or a Find job id from a previous command. --- The MCP tool name is `get_status`. HTTP is `GET /api/v1/status/:id` with `Authorization: Bearer rmr_...`. Poll a handle from a previous write. Replace `THREAD_ID` with the comment thread `id`, or with a Find job `id`. Keep calling until `identity` is an object, or until Find `cards` has URLs. ## Request Set `HOST` to `https://rumora.ai` in production. Replace `rmr_YOUR_TOKEN` with the full secret from **API keys**. Replace `THREAD_ID` with the `id` from `post_comment`, `post_thread`, or `find_videos`. ```bash curl -sS "$HOST/api/v1/status/THREAD_ID" \ -H "Authorization: Bearer rmr_YOUR_TOKEN" ``` You should see JSON that includes `id`, `type`, `status`, `credits_charged`, `next_step`. If you see `"error"`, match `code` in [Errors](/docs/api/errors). ## Response ```json { "id": "THREAD_ID", "type": "thread", "status": "live", "credits_charged": 25, "identity": { "platform": "youtube", "comment_id": "COMMENT_ID", "username": "posted_name", "video_url": "https://www.youtube.com/watch?v=VIDEO", "youtube_like_url": "https://www.youtube.com/watch?v=VIDEO&lc=COMMENT_ID" }, "next_step": "Like with watch?v= plus lc=COMMENT_ID. Reply with the video URL plus the posted username. Do not send lc on reply." } ``` A Find job uses the same route. Poll until `cards` has URLs, or until `"status": "refunded"`. ```json { "id": "JOB_ID", "type": "find", "status": "done", "credits_charged": 50, "step": "done", "error": null, "cards": [ { "id": "CARD_ID", "video_id": "VIDEO_ROW_ID", "url": "https://www.youtube.com/watch?v=VIDEO", "title": "Example title", "skipped": false } ], "next_step": "Pick a video URL from cards and call post_comment or post_thread." } ``` ## Errors - [`UNAUTHORIZED`](/docs/api/errors): Mint a key on API keys. Send Authorization: Bearer rmr_... - [`NOT_FOUND`](/docs/api/errors): Check the path and the id from the previous command. The JSON error envelope is documented in [Errors](/docs/api/errors). ## Credits None. This command is read only. ## Next If type is thread and identity is present, like or reply with those fields. If type is find and cards exist, copy a url and call post_comment. If status is refunded, change keywords and start a new Find job. A full copy-paste job that uses this command is in [Recipes](/docs/recipes). Identity and polling are explained in [Comment identity](/docs/concepts/identity) and [Status and polling](/docs/concepts/status-and-polling). # /docs/reference/get-usage --- title: get_usage description: Return remaining credits and live limits for YouTube and TikTok. --- The MCP tool name is `get_usage`. HTTP is `GET /api/v1/usage` with `Authorization: Bearer rmr_...`. Call this before every write. It spends nothing. Copy `commentMaxLength` and `likeMin` for the platform you will post on, and confirm `credits_left` covers the next command. ## Request This command has no JSON body. MCP sends an empty arguments object. HTTP sends only the Authorization header. Set `HOST` to `https://rumora.ai` in production. Replace `rmr_YOUR_TOKEN` with the full secret from **API keys**. ```bash curl -sS "$HOST/api/v1/usage" \ -H "Authorization: Bearer rmr_YOUR_TOKEN" ``` You should see JSON that includes `credits_left`, `checkout_url`, `find_enabled`, `comment_credits`, `like_credits`, `find_credits`, `limits`. If you see `"error"`, match `code` in [Errors](/docs/api/errors). ## Response ```json { "credits_left": 1500, "checkout_url": "https://rumora.ai/home/acme/billing", "find_enabled": true, "comment_credits": 25, "like_credits": 1, "find_credits": 50, "limits": { "youtube": { "canComment": true, "canReply": true, "canLike": true, "commentMaxLength": 200, "replyMaxLength": 200, "likeMin": 25, "likeMax": 200, "minCommentsPerOrder": 1, "commentCredits": 25, "replyCredits": 25, "likeCredits": 1, "findCredits": 50 }, "tiktok": { "canComment": true, "canReply": true, "canLike": true, "commentMaxLength": 200, "replyMaxLength": 200, "likeMin": 25, "likeMax": 200, "minCommentsPerOrder": 1, "commentCredits": 25, "replyCredits": 25, "likeCredits": 1, "findCredits": 50 } } } ``` ## Errors - [`UNAUTHORIZED`](/docs/api/errors): Mint a key on API keys. Send Authorization: Bearer rmr_... The JSON error envelope is documented in [Errors](/docs/api/errors). ## Credits None. This command is read only. ## Next Copy commentMaxLength and likeMin for the platform you will post on. Do not hardcode those numbers from an older page. Then call post_comment, post_thread, or find_videos. A full copy-paste job that uses this command is in [Recipes](/docs/recipes). Identity and polling are explained in [Comment identity](/docs/concepts/identity) and [Status and polling](/docs/concepts/status-and-polling). # /docs/reference --- title: Command reference description: One page per program command. MCP and REST share the same runner and the same JSON. --- Each page is one command. MCP and REST share the same JSON, so you read one page, not two contracts. Open [Playground](/docs/playground) from the page header to run it live. Call [get_usage](/docs/reference/get-usage) before a write. Live max length and like minimums can change. # /docs/reference/like-comment --- title: like_comment description: Like a live comment using the identity Rumora returns. --- The MCP tool name is `like_comment`. HTTP is `POST /api/v1/comments/like` with `Authorization: Bearer rmr_...`. Likes a comment that is already live. Copy identity from `get_status` first. YouTube uses `url` with `lc=`. TikTok uses `video_url` plus `username`. Set `quantity` to `likeMin` or higher from `get_usage`. 1 credit per like. Quantity below likeMin from get_usage is an error. Call get_usage first and read the live number. ## Request Set `HOST` to `https://rumora.ai` in production. Replace `rmr_YOUR_TOKEN` with the full secret from **API keys**. Set `quantity` to `likeMin` or higher from `get_usage`. Use a **new** idempotency key, not the one from `post_comment`. **YouTube.** Paste `identity.youtube_like_url` into `url`. ```bash curl -sS -X POST "$HOST/api/v1/comments/like" \ -H "Authorization: Bearer rmr_YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "url": "https://www.youtube.com/watch?v=VIDEO&lc=COMMENT_ID", "quantity": 25, "idempotency_key": "like-1" }' ``` **TikTok.** Paste `identity.video_url` and `identity.username`. Do not send `url` with `lc=`. ```bash curl -sS -X POST "$HOST/api/v1/comments/like" \ -H "Authorization: Bearer rmr_YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "video_url": "https://www.tiktok.com/@user/video/VIDEO", "username": "posted_name", "quantity": 25, "idempotency_key": "like-1" }' ``` You should see JSON that includes `id`, `type`, `status`, `credits_charged`, `credits_remaining`, `quantity`, `line_id`, `identity`, `next_step`. If you see `"error"`, match `code` in [Errors](/docs/api/errors). ## Response ```json { "id": "THREAD_ID", "type": "like", "status": "queued", "credits_charged": 25, "credits_remaining": 1450, "quantity": 25, "line_id": "LINE_ID", "identity": { "platform": "youtube", "comment_id": "COMMENT_ID", "video_id": "VIDEO" }, "next_step": "Poll get_status. Likes are queued on the same identity Rumora returned." } ``` ## Errors - [`UNAUTHORIZED`](/docs/api/errors): Mint a key on API keys. Send Authorization: Bearer rmr_... - [`PARSE`](/docs/api/errors): Fix the field named in message. Call get_usage for live max length. - [`PLATFORM`](/docs/api/errors): Pass a YouTube watch or Shorts URL, or a TikTok video URL. - [`QUANTITY`](/docs/api/errors): Send at least min from the error body. Rumora will not raise a low quantity. - [`PAYMENT_REQUIRED`](/docs/api/errors): Open checkout_url from the error body. Buy a plan or an add-on pack, then retry with the same idempotency_key. - [`HELD`](/docs/api/errors): Contact support. Mutating commands stay blocked until the hold clears. - [`PROVIDER`](/docs/api/errors): Call get_usage. If canComment, canReply, or canLike is false, that action is unavailable. - [`RATE_LIMIT`](/docs/api/errors): Wait, then retry with the same idempotency_key. Reads are not counted. The JSON error envelope is documented in [Errors](/docs/api/errors). ## Credits 1 credit per like. Quantity below likeMin from get_usage is an error. ## Next Do not send share_comment_id or cid. On TikTok, if two comments share one owner username on the same video, Rumora cannot tell them apart. A full copy-paste job that uses this command is in [Recipes](/docs/recipes). Identity and polling are explained in [Comment identity](/docs/concepts/identity) and [Status and polling](/docs/concepts/status-and-polling). # /docs/reference/post-comment --- title: post_comment description: Post one top-level comment. Text only. Does not like. --- The MCP tool name is `post_comment`. HTTP is `POST /api/v1/comments` with `Authorization: Bearer rmr_...`. Posts one top-level comment. It does not like. Copy `id` from the response, then poll `get_status` until `identity` is an object before you like or reply. 25 credits leave the wallet at submit, before the comment is live. Call get_usage first and read the live number. ## Request Set `HOST` to `https://rumora.ai` in production. Replace `rmr_YOUR_TOKEN` with the full secret from **API keys**. Keep `idempotency_key` at least 8 characters and reuse it if this request times out. ```bash curl -sS -X POST "$HOST/api/v1/comments" \ -H "Authorization: Bearer rmr_YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "video_url": "https://www.youtube.com/watch?v=VIDEO", "text": "Useful breakdown of this.", "idempotency_key": "comment-1" }' ``` You should see JSON that includes `id`, `type`, `status`, `credits_charged`, `credits_remaining`, `video_id`, `line_id`, `next_step`. If you see `"error"`, match `code` in [Errors](/docs/api/errors). ## Response ```json { "id": "THREAD_ID", "type": "thread", "status": "queued", "credits_charged": 25, "credits_remaining": 1475, "video_id": "VIDEO_ROW_ID", "line_id": "LINE_ID", "next_step": "Poll get_status until the comment is live, then like_comment or reply_to_comment with the returned identity." } ``` ## Errors - [`UNAUTHORIZED`](/docs/api/errors): Mint a key on API keys. Send Authorization: Bearer rmr_... - [`PARSE`](/docs/api/errors): Fix the field named in message. Call get_usage for live max length. - [`PLATFORM`](/docs/api/errors): Pass a YouTube watch or Shorts URL, or a TikTok video URL. - [`PAYMENT_REQUIRED`](/docs/api/errors): Open checkout_url from the error body. Buy a plan or an add-on pack, then retry with the same idempotency_key. - [`HELD`](/docs/api/errors): Contact support. Mutating commands stay blocked until the hold clears. - [`OPTED_OUT`](/docs/api/errors): Pick a different video. Existing live comments on that video stay. - [`PROVIDER`](/docs/api/errors): Call get_usage. If canComment, canReply, or canLike is false, that action is unavailable. - [`RATE_LIMIT`](/docs/api/errors): Wait, then retry with the same idempotency_key. Reads are not counted. The JSON error envelope is documented in [Errors](/docs/api/errors). ## Credits 25 credits leave the wallet at submit, before the comment is live. ## Next Copy id, then poll get_status until identity is an object. Do not send likes in this body. Home paste is Shorts and TikTok only. This command also accepts YouTube watch URLs. A full copy-paste job that uses this command is in [Recipes](/docs/recipes). Identity and polling are explained in [Comment identity](/docs/concepts/identity) and [Status and polling](/docs/concepts/status-and-polling). # /docs/reference/post-thread --- title: post_thread description: Post a parent comment plus replies you wrote. No likes field. --- The MCP tool name is `post_thread`. HTTP is `POST /api/v1/threads` with `Authorization: Bearer rmr_...`. Sends a parent comment plus replies you already wrote. Rumora does not generate replies. Do not send `likes`. Poll `get_status` until the parent is live, then like with `like_comment` if you want likes. 25 credits per line. Parent plus each reply. Call get_usage first and read the live number. ## Request Set `HOST` to `https://rumora.ai` in production. Replace `rmr_YOUR_TOKEN` with the full secret from **API keys**. Keep `idempotency_key` at least 8 characters and reuse it if this request times out. ```bash curl -sS -X POST "$HOST/api/v1/threads" \ -H "Authorization: Bearer rmr_YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "video_url": "https://www.youtube.com/watch?v=VIDEO", "parent": "The pricing section is the part that matters.", "replies": [ { "content": "The demo at 3:12 is the same claim.", "wait_hours": 2 } ], "idempotency_key": "thread-1" }' ``` You should see JSON that includes `id`, `type`, `status`, `credits_charged`, `credits_remaining`, `line_count`, `next_step`. If you see `"error"`, match `code` in [Errors](/docs/api/errors). ## Response ```json { "id": "THREAD_ID", "type": "thread", "status": "queued", "credits_charged": 50, "credits_remaining": 1450, "line_count": 2, "next_step": "Poll get_status. Replies dispatch after the parent comment is live." } ``` ## Errors - [`UNAUTHORIZED`](/docs/api/errors): Mint a key on API keys. Send Authorization: Bearer rmr_... - [`PARSE`](/docs/api/errors): Fix the field named in message. Call get_usage for live max length. - [`PLATFORM`](/docs/api/errors): Pass a YouTube watch or Shorts URL, or a TikTok video URL. - [`PAYMENT_REQUIRED`](/docs/api/errors): Open checkout_url from the error body. Buy a plan or an add-on pack, then retry with the same idempotency_key. - [`HELD`](/docs/api/errors): Contact support. Mutating commands stay blocked until the hold clears. - [`OPTED_OUT`](/docs/api/errors): Pick a different video. Existing live comments on that video stay. - [`PROVIDER`](/docs/api/errors): Call get_usage. If canComment, canReply, or canLike is false, that action is unavailable. - [`RATE_LIMIT`](/docs/api/errors): Wait, then retry with the same idempotency_key. Reads are not counted. The JSON error envelope is documented in [Errors](/docs/api/errors). ## Credits 25 credits per line. Parent plus each reply. ## Next Do not send likes in this body. Poll get_status until identity appears, then like live lines with like_comment. A full copy-paste job that uses this command is in [Recipes](/docs/recipes). Identity and polling are explained in [Comment identity](/docs/concepts/identity) and [Status and polling](/docs/concepts/status-and-polling). # /docs/reference/reply-to-comment --- title: reply_to_comment description: Reply to a live comment. Pass the video URL plus the parent owner username. --- The MCP tool name is `reply_to_comment`. HTTP is `POST /api/v1/comments/reply` with `Authorization: Bearer rmr_...`. Replies to a live comment. Send the video URL plus the parent owner `username`. Do not send an `lc=` URL. Copy those fields from `get_status` identity. 25 credits leave the wallet at submit. Call get_usage first and read the live number. ## Request Set `HOST` to `https://rumora.ai` in production. Replace `rmr_YOUR_TOKEN` with the full secret from **API keys**. Keep `idempotency_key` at least 8 characters and reuse it if this request times out. ```bash curl -sS -X POST "$HOST/api/v1/comments/reply" \ -H "Authorization: Bearer rmr_YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "video_url": "https://www.youtube.com/watch?v=VIDEO", "username": "posted_name", "text": "Agree on the pricing point.", "wait_hours": 0, "idempotency_key": "reply-1" }' ``` You should see JSON that includes `id`, `type`, `status`, `credits_charged`, `credits_remaining`, `line_id`, `identity`, `next_step`. If you see `"error"`, match `code` in [Errors](/docs/api/errors). ## Response ```json { "id": "THREAD_ID", "type": "reply", "status": "queued", "credits_charged": 25, "credits_remaining": 1450, "line_id": "LINE_ID", "identity": { "platform": "youtube", "username": "posted_name", "video_url": "https://www.youtube.com/watch?v=VIDEO" }, "next_step": "Poll get_status. The reply uses the video URL plus username of the agent who posted the parent comment." } ``` ## Errors - [`UNAUTHORIZED`](/docs/api/errors): Mint a key on API keys. Send Authorization: Bearer rmr_... - [`PARSE`](/docs/api/errors): Fix the field named in message. Call get_usage for live max length. - [`PLATFORM`](/docs/api/errors): Pass a YouTube watch or Shorts URL, or a TikTok video URL. - [`PAYMENT_REQUIRED`](/docs/api/errors): Open checkout_url from the error body. Buy a plan or an add-on pack, then retry with the same idempotency_key. - [`HELD`](/docs/api/errors): Contact support. Mutating commands stay blocked until the hold clears. - [`OPTED_OUT`](/docs/api/errors): Pick a different video. Existing live comments on that video stay. - [`PROVIDER`](/docs/api/errors): Call get_usage. If canComment, canReply, or canLike is false, that action is unavailable. - [`RATE_LIMIT`](/docs/api/errors): Wait, then retry with the same idempotency_key. Reads are not counted. The JSON error envelope is documented in [Errors](/docs/api/errors). ## Credits 25 credits leave the wallet at submit. ## Next Do not pass a YouTube lc URL, cid, or share_comment_id. Replies use the video URL plus the parent owner username. A full copy-paste job that uses this command is in [Recipes](/docs/recipes). Identity and polling are explained in [Comment identity](/docs/concepts/identity) and [Status and polling](/docs/concepts/status-and-polling). # /docs/troubleshooting --- title: Troubleshooting description: Match the error or the symptom, then take the next action. icon: CircleAlert --- Start with `error.code` when the JSON includes one. If the client only shows a symptom, use the second list. Every item says what to do next, not only what went wrong. ## You have an error code The server did not accept the Bearer token. Open **API keys**, click **Create key**, and copy the full secret. Send `Authorization: Bearer rmr_...` with that full string. A revoked secret stays dead. Rotating is [Rotate a token](/docs/recipes/rotate-a-token). The workspace does not have enough credits. Open `checkout_url` from the error body, buy a plan or a pack, then retry the **same** `idempotency_key`. The workspace is on hold. Stop writes. Contact support. Reads such as `get_usage` still work. Find needs an active paid plan. Open **Billing** and start a plan, or [paste a URL](/docs/using/paste) and post without Find. That creator opted out of Rumora. Pick a different video. Comments already live on their videos stay. The path is wrong, or the thread id / Find job id is not in this workspace. Copy `id` from the previous success JSON and paste it into `GET /api/v1/status/:id`. A Find job is already open. Copy `job_id` from the error body and poll `get_status` on that id. Wait until it finishes before starting another search. This workspace sent 10 writes in 60 seconds. Wait, then retry with the **same** `idempotency_key`. `get_usage` and `get_status` do not count. The body failed validation. Read `message`. Common cases: `likes` on `post_comment`, an `lc` URL on reply, `cid` or `share_comment_id`, an `idempotency_key` shorter than 8 characters, or text over `commentMaxLength`. Like `quantity` is below `likeMin` or above `likeMax`. The error body includes `min` and `max`. Send at least `min`. Rumora will not raise a low number. The URL is not YouTube or TikTok. Instagram and other hosts are rejected. Pass a YouTube watch or Shorts URL, or a TikTok video URL. That action is not available on this platform right now, or Rumora could not complete it. Call `get_usage`. If `canComment`, `canReply`, or `canLike` is false for that platform, that action is unavailable right now. The HTTP status for each code is in [Errors](/docs/api/errors). ## You have a symptom You liked before `identity` existed. Poll `get_status` until `identity` is an object. Then send a YouTube `lc=` URL or a TikTok `video_url` plus `username`. See [Comment identity](/docs/concepts/identity). The parent comment is not `live` yet. Keep polling every few seconds. If it never lands, open **Threads** in the web app and look up the same id. When `status` is `refunded`, the credits came back. Change the keywords and start a new Find job with a new `idempotency_key`. Rumora keys TikTok likes and replies by video URL plus username. Two comments from the same user on the same video cannot be distinguished. Like one of them, or pick a different username. The `idempotency_key` changed between attempts. Reuse the same key for the same job. See [Idempotency](/docs/concepts/idempotency). The MCP server only accepts the MCP POST transport. Do not open `/api/mcp` in a browser. Sideload JSON is in [Sideload the MCP server](/docs/mcp/sideload). Home paste is Shorts and TikTok only. Use a Shorts URL, run Find, or pass the watch URL to `post_comment` from an agent. # /docs/using/agent-access --- title: Create an API key description: Mint a workspace key on the API keys page. Personal accounts have no key. --- When you finish this page, you have a secret that starts with `rmr_` and you have copied it into Cursor, Claude Code, the playground, or a script. That secret spends this team's credits. ## Steps 1. Open the **team** workspace. Personal accounts have no API keys page. 2. Click **API keys** in the sidebar. 3. Click **Create key**. 4. Copy the full secret immediately. Click **Copy key** if you need it again on that screen. The secret is shown once. After a reload the page keeps only the `rmr_` prefix. Last used stays empty until MCP or REST accepts the key. Put the secret in: - The [playground](/docs/playground) Authorization field, to try a call in the browser. - Cursor or Claude MCP settings. The JSON is on **MCP** and in [Sideload the MCP server](/docs/mcp/sideload). - An `Authorization: Bearer rmr_...` header in curl. Only members who can manage settings can create or revoke a key. Everyone else can view the prefix. To rotate a leaked secret, follow [Rotate a token](/docs/recipes/rotate-a-token). # /docs/using/billing --- title: Buy a plan description: Open team Billing to start a plan or an add-on pack. checkout_url from PAYMENT_REQUIRED points here. --- When you finish this page, the team has an active plan or extra add-on credits, and the header balance has gone up. MCP and REST spend this same pool. Use this when **Home** has no credits left, or when an agent error includes `checkout_url`. ## Steps 1. Open the **team** workspace. Plans live on that team, not on a personal account. 2. Click **Billing**. 3. If there is no plan, click **Choose a plan** and finish checkout. 4. If the subscription ended, click **Restart plan**. 5. After a paid plan is active, click **Buy credits** if you want an add-on pack on top of the monthly pool. You should see the new balance in the header. Find needs an active paid plan. A free grant can still [paste a video URL](/docs/using/paste) and post. Only members who can manage billing can start checkout. Everyone else sees a warning on this page. `PAYMENT_REQUIRED` from an agent points `checkout_url` at this **Billing** page for the token's team. After you pay, retry the failed call with the **same** `idempotency_key`. # /docs/using/comments --- title: Post a comment, reply, and like description: Open a video, post from the composer, then reply or like after the line is live. --- When you finish any section on this page, a comment, reply, or like is in progress on a video that is already in the workspace. To add a URL first, [paste a video URL](/docs/using/paste) or [Find videos](/docs/using/find). ## Post a comment 1. Open the video from **Home**. 2. If **Generate** is disabled, go back to **Home**, fill **Product name**, **What it is**, and **Why it is better**, then open the video again. 3. Type the parent comment, or click **Generate** and edit the draft until you would post it yourself. 4. Stay under the live max length shown in the composer. 5. Click **Post**. Credits leave the workspace at submit. A kept line costs `comment_credits` from `get_usage` (25 today). You should see the thread move toward live. If you leave the video, open **Threads**. Do not expect likes to go out in that same agent call. `post_comment` rejects a `likes` field. In the web app, **Add likes** on the same submit still waits for the comment to land. ## Reply Wait until the parent is live. If the composer still says the line is posting, wait. 1. Write the reply in the composer or on the live thread. Keep only lines you wrote or edited. 2. Stay under the live reply max length. 3. Send the reply. A reply is another comment line. It costs the same `comment_credits` as the parent. If you send the reply from MCP or REST, pass the video URL plus the parent owner username. Do not pass a YouTube `lc` URL, a `cid`, or a share-comment id. The fields are in [Comment identity](/docs/concepts/identity). ## Like If you want likes in the same web submit, click **Add likes** and set quantity at or above the minimum in the composer. If you like after the comment is live: - YouTube: use `watch?v=` plus `lc=` and the comment id. - TikTok: use the video URL plus the comment owner username. If quantity is below the live minimum, MCP and REST return `QUANTITY`. Rumora will not raise it. A like costs `like_credits` each (1 today). Trust `get_usage` for `likeMin`. ## From an agent Follow [Comment then like](/docs/recipes/comment-then-like) for the curl. The MCP JSON is in [Recommended workflow](/docs/mcp/workflow). The short order is: 1. `get_usage` 2. `post_comment` with `video_url`, `text`, and `idempotency_key` 3. `get_status` until `identity` is an object 4. `like_comment` or `reply_to_comment` with those identity fields # /docs/using/credits --- title: Check remaining credits description: Read the team wallet before you post or search. Agents spend this same pool. --- When you finish this page, you know how many credits the open team has left, and whether you need to buy more before a post or a Find. Credits live on the team workspace. Personal accounts do not hold this wallet. The rule is in [Workspace and credits](/docs/concepts/workspace-and-credits). ## In the web app 1. Open the team you will spend from. 2. Read the credits count in the header. 3. Click the chip to see **Monthly credits** or **Included credits**, plus **Add-on credits**. You should see one remaining balance. MCP and REST spend this same number. ## From an agent ```bash curl -sS "$HOST/api/v1/usage" \ -H "Authorization: Bearer $TOKEN" ``` Read `credits_left`. Also read `comment_credits`, `like_credits`, and `find_credits` so you know what the next call will spend. Today a comment or reply line is 25 credits, a like is 1 credit, and Find is 50 credits per keyword. Trust `get_usage` and the composer for live limits. If the balance is too low, [buy a plan](/docs/using/billing). `PAYMENT_REQUIRED` includes `checkout_url` for that **Billing** page. # /docs/using/find --- title: Find videos description: Search YouTube or TikTok by keyword on a paid plan, then pick a card to comment. --- When you finish this page, you will have run a keyword search and opened one result so you can comment. Find does not paste the video and does not post the comment. You pick a card. Find is paid-plan only. Each keyword costs `find_credits` from `get_usage` (50 today). If Find is locked, [buy a plan](/docs/using/billing) or [paste a video URL](/docs/using/paste). ## Steps 1. Open **Home** in the team workspace. 2. If Search says to add product details first, fill **Product name**, **What it is**, and **Why it is better**. 3. Click **Search**. 4. Choose **YouTube** or **TikTok**. 5. Type a keyword and click **Add**. Or click **Get inspired** and pick **1 keyword**, **3 keywords**, **5 keywords**, or **10 keywords**, then edit the list. 6. Credits are not taken until you click **Search**. The button shows the cost when keywords are present. 7. Click **Search**. You should land on **Search results**. The page stays up to date while the job runs. When cards appear: 1. Pick a video. 2. Click **Open** or **Keep on shelf**. 3. Comment from that video. See [Post a comment, reply, and like](/docs/using/comments). A second open Find job for the workspace is blocked until the first finishes. Empty finds refund the Find credits. From an agent, use [Find then comment](/docs/recipes/find-then-comment). # /docs/using --- title: Using Rumora description: How-tos for jobs in the signed-in web app. Paste, comment, Find, bill, and connect an agent. --- These pages are click-by-click in the team workspace. Open the team you want to spend from before you start. Personal accounts do not hold this wallet. If you want curl or MCP instead, use [First agent request](/docs/first-agent-request) or [Recipes](/docs/recipes). Add a YouTube Short or TikTok video from Home. This is free. Write in the composer, then reply or like after the line is live. Search by keyword on a paid plan, then pick a card. See queued and live work. The id in the URL is what get_status polls. Read the workspace wallet before you post or search. Open Billing when the header or an error says you need credits. Send invites from the Members page. Mint a key on the API keys page. Stop future targeting of a public channel. # /docs/using/members --- title: Invite teammates description: Send email invites from the Members page on the team that holds the wallet. --- When you finish this page, someone else has an invite to this team so they can use **Home**, **Threads**, and **Settings** on the same wallet. ## Steps 1. Open the team workspace. 2. Click **Members**. 3. Click **Invite**. 4. Enter an email and a role in **Invite people**. 5. Click **Send invites**. You should see the person under **Pending invites** until they accept. After they join, they appear under **Team**. If the plan has no seats left, the button is **Upgrade to invite** and opens **Billing**. Credits stay on the team. A member with permission to manage settings can [create an API key](/docs/using/agent-access). Personal accounts are not this page. # /docs/using/opt-out --- title: Opt a channel out of Find description: Stop future targeting of a public channel. Existing comments stay. --- When you finish this page, Rumora will skip that YouTube channel in future Find jobs. Comments already on the videos stay. You do not need a Rumora account for this form. ## Steps 1. Open [Creator opt-out](/opt-out). The site footer also links this form as **Opt out**. 2. Choose **YouTube**. Instagram and TikTok show **Coming soon**. 3. Click **Start opt-out**. 4. Enter the **YouTube channel URL** and click **Verify**. 5. Fill **First name**, **Last name**, **Email**, and **Why are you opting out?** 6. Click **Opt this channel out**. You should see **This channel is out of Find.** Future Find jobs skip that channel. Mutating program commands on that creator return `OPTED_OUT`. Pick a different video. # /docs/using/paste --- title: Paste a video URL description: Add a YouTube Short or TikTok video from Home without spending credits. --- When you finish this page, a video is on **Home** and you can open it to comment. Paste does not spend credits. Posting later does. Use this when you already have a URL. If you do not, [Find videos](/docs/using/find) instead. ## Steps 1. Sign in and open the **team** workspace. Credits live on that team. 2. Go to **Home**. 3. If **Search** is selected, click **Paste URL**. 4. Paste a YouTube Shorts URL or a TikTok video URL. You can paste more than one line. 5. Click **Continue**. You should see the video on **Home**. Click it, then [post a comment, reply, and like](/docs/using/comments). The field says **Free to add. YouTube Shorts and TikTok only.** A regular YouTube watch URL, a channel, a playlist, or an Instagram link fails here. If the creator opted out, that URL is skipped. An agent can still pass a watch URL to `post_comment`. There is no paste command on MCP or REST. An agent passes `video_url` on `post_comment` instead. # /docs/using/threads --- title: Open Threads description: See queued and live work. The thread id is the same handle get_status polls. --- When you finish this page, you have opened a thread you posted earlier and can see whether it is still queued or already live. If you have not spent credits on a search or a thread yet, **Threads** stays locked. The sidebar says **Available after you use credits on a search or thread.** Post or Find first. ## Steps 1. Open the team workspace. 2. Click **Threads**. 3. Click a card. You should see the parent, replies, and status. The id in the URL is the `id` that MCP and REST pass to `get_status`. Identity on a live parent is the same object those APIs return. If the list is empty after you have spent credits, the page says **No threads yet** and **Search or paste on Home.** Go to [Paste a video URL](/docs/using/paste).