Approval inbox
How agent-proposed actions work in RankParse. An agent proposes, a person approves in the dashboard, and only then does anything run.
An AI agent that can send email and submit URLs on your behalf needs a brake. The approval inbox is that brake. Instead of acting, the agent proposes an action. The proposal lands in your inbox in the RankParse dashboard, you read exactly what would happen, and only your approval makes it run.
This page explains the model. The API details are in Proposals, Agent tasks and activity, Websites and Client report.
The one rule: approval happens only in the RankParse web app, by a signed-in person. No API key, MCP tool or connector can approve, skip or run a proposal. An agent can fill your inbox, never empty it.
How it works
Agent RankParse API Person (web app)
| | |
| 1. POST /v1/proposals | |
|---------------------------->| stores a pending proposal |
|<--- 202 awaiting_approval --| |
| proposal_id, review_url |-- daily email: items waiting ->|
| | |
| 2. shows review_url to user | 3. opens the inbox, reads every URL or email,
| | removes items, approves or skips
| |<------------- approve ---------|
| | 4. runs exactly what was approved
| | (charges credits, sends, submits)
| 5. GET /v1/proposals/:id | |
|---------------------------->| |
|<--- succeeded, result ------| |
| 6. POST /v1/activity (optional note) |- Propose. The agent calls
POST /v1/proposals(or an MCP propose tool). Nothing runs. It gets back aproposal_idand areview_url. - Tell the person. The agent shows the
review_url. RankParse also lists the item in the website's Today page and the workspace inbox, and emails a daily digest. - Review. The person sees the proposal's real content (the actual URLs, or every outreach email with its recipient, subject and body). They can remove individual emails, then approve or skip.
- Run. On approval RankParse runs the exact snapshot that was approved. If the content changed after approval, the run is refused.
- Read the outcome. The agent polls
GET /v1/proposals/:idor lists withGET /v1/proposals. The status ends assucceeded,partially_succeededorfailedwith anerror_code. - Report back (optional). The agent logs a short note to the activity feed and, for queued tasks, completes them with a summary.
What an agent can propose
| Kind | What it does when approved | Credits | Can run without a person? |
|---|---|---|---|
indexnow_submit | Submits up to 1000 URLs on one of your websites to IndexNow (Bing, Yandex, Seznam, Naver and others). | 1 when it runs, refunded if the submission fails | Only if you set that website's policy to Automatic |
outreach_send | Queues the reviewed outreach emails for sending from your connected Gmail account. | 0 | Never. Outreach always waits for a person. |
RankParse itself also creates items for your inbox, which you can approve like any other:
- Rank-drop investigations. For websites with rank-change alerts on, a keyword that dropped can produce a proposal. Approving it creates a task asking your agent to find the cause. At most 3 a day per website.
- Pages not confirmed as indexed. For tracked pages older than 2 days without a clean Search Console indexing result, RankParse can suggest submitting them to IndexNow, at most once a day per website.
- Raising the sending limit. When an agent tries to raise the daily Gmail send cap or switch auto-send on, that change becomes a proposal. Lowering the cap or switching sending off always applies immediately, because stopping is always allowed.
Agents can only create indexnow_submit and outreach_send proposals through the API. The others come from RankParse.
Who can approve
Owners, admins and members of the workspace can approve proposals, subject to the permission each kind needs (outreach needs permission to send outreach; IndexNow needs permission to spend credits and edit the website). Client accounts never see the inbox. RankParse re-checks the approver's permission when the action runs, so a role removed after approval stops the run (approver_lost_permission).
What the agent may do without asking
Each website has a settings section called What the agent may do without asking. Owners and admins can change it. Each action has a mode:
| Action | Modes | Default | Notes |
|---|---|---|---|
| Submit pages to IndexNow | Ask first, Automatic, Off | Ask first | Automatic has a daily URL limit: 200 by default, 1000 at most. Past the limit, proposals wait for approval. |
| Suggest indexing for pages Google has not confirmed as indexed | Ask first, Automatic, Off | Ask first | Automatic uses the same IndexNow daily limit. |
| Send outreach emails | Ask first, Off | Ask first | Cannot be Automatic. You see every email before anything is sent. |
| Raise the daily send limit or turn sending on | Ask first, Off | Ask first | Lowering or pausing never needs approval. |
| Suggest investigating ranking drops | Ask first, Off | Ask first | Only for websites with rank alerts on. |
Off means the API refuses the proposal outright with 403 action_disabled_by_policy. A website's setting overrides a workspace-wide default, which overrides the built-in default.
Where approval is enforced
The inbox protects actions that come from an agent. RankParse treats a request as agent-origin when it carries the header X-RankParse-Client: mcp, which the RankParse MCP server sets on every call. In an account where the inbox is enforced:
| Request | What happens |
|---|---|
MCP tool outreach_launch_campaign (or POST /v1/outreach/campaigns/:id/launch with the header) | Creates an outreach_send proposal and returns status: "awaiting_approval" with a review_url. Nothing is queued. |
MCP tool submit_indexnow_urls (or POST /v1/indexnow with the header) | Creates an indexnow_submit proposal instead of submitting, unless the website's policy is Automatic. |
MCP tool outreach_configure_sending raising the cap or enabling auto-send | Becomes a proposal. Any decrease or disable in the same request applies immediately. |
| A button you click in the dashboard | Your click is the approval. It runs now. |
| A direct REST call without that header | Runs immediately, exactly as before. |
| RapidAPI calls | Never agent-origin, so never diverted. |
The approval guarantee covers agents that go through the RankParse MCP server, or that send the X-RankParse-Client: mcp header. A script that calls the REST API directly with your key is acting as you, and is not stopped. Keep API keys private, and use Dashboard keys to revoke any you no longer trust.
Proposal lifecycle
pending --approve--> approved --> executing --> succeeded
| | | \--> partially_succeeded
| | \------> failed --retry--> approved
|--skip----------> skipped
|--no decision---> expired
|--newer proposal-> superseded
\--all emails removed--> cancelled| Status | Meaning |
|---|---|
pending | Waiting for a person. |
approved | Approved by a person or an Automatic policy. About to run, or waiting for a retry. |
executing | Running now. |
succeeded | Done. The proposal's result has counts. |
partially_succeeded | Outreach only: some emails were queued, others had changed or were suppressed. |
failed | Did not complete. error_code says why. A person can retry it in the app. |
skipped | A person declined it. |
expired | Nobody decided in time. |
superseded | Replaced by a newer proposal for the same outreach campaign. |
cancelled | A reviewer removed every email, so nothing was left to send. |
Expiry
A pending proposal expires if nobody decides in time:
| Kind | Expires after |
|---|---|
| Outreach send | 14 days |
| IndexNow submission | 7 days |
| Sending limit change | 3 days |
| Rank-drop investigation | 7 days |
Expired proposals disappear from the pending count and the digest. Propose again if the action is still wanted.
Reliability and safety
- Exact snapshot. An outreach proposal records each email's content hash, and an IndexNow proposal its URL list. Approval binds to that hash. If an email's content changes after you reviewed it, that email is not sent (it is reported as changed since review).
- At most once per decision. A run is claimed with a lease. A crashed or timed-out run is picked up again by an hourly recovery job, starting 10 minutes after approval, up to 5 attempts. Charges are applied once and refunded on failure.
- Duplicates collapse. Proposing the same content twice returns the same proposal (
dedupe_hit: true), so retries are safe. - Text is sanitized. Agent-written notes are cleaned of control and invisible characters and shown labelled as the agent's words. The title of a proposal is always built by RankParse from the stored data, never from agent text.
- Isolation. A proposal, task or website of another account returns
404. A workspace id can never be supplied by a caller.
Limits
| Limit | Value |
|---|---|
| Pending proposals per website | 25 |
| New proposals per account per UTC day | 100 |
| Activity notes per account per UTC day | 200 |
| URLs per IndexNow proposal | 1000 |
| Emails per agent outreach proposal | 100 |
| Requests per minute | 60 |
Activity log
Everything that happens around an inbox item is recorded in the website's activity feed: proposal created, approved, skipped, expired, succeeded or failed; IndexNow submitted; outreach sent; tasks created, claimed and completed; policy changes.
Agents can add their own entries with POST /v1/activity (MCP tool log_activity). RankParse also attaches the calls your agent made, and the credits they used, to those notes automatically, so you can see what a piece of research cost without the agent reporting it. See Agent tasks and activity.
Agent tasks
Tasks flow the other way. A person leaves a job ("Find links my competitors have"), the agent reads its queue with GET /v1/agent-tasks, works on it using the normal tools, and calls POST /v1/agent-tasks/:id/complete with a summary the person sees in the app. Claiming is optional; completing an open task claims it. See Agent tasks.
Daily digest email
When something is waiting for a decision, RankParse emails each non-client member of the workspace at most once per day (sent in the afternoon, UTC) with the number of items waiting, per workspace and website. No items means no email. A send that fails is retried later the same day. Each person can switch it off under Account, with the toggle Daily email when items are waiting for your OK. The email never contains proposal content.
Client reports
Work that is safe to show a client appears in the weekly client report: IndexNow submissions, outreach emails sent per day, rank moves, and any agent note or task summary a team member chose to share. Approvals, policy changes, credit use and everything else stay private to the team.
Retention
| Data | Kept for |
|---|---|
| Activity feed events | 400 days |
| Finished proposals (any terminal status) | 400 days |
| Agent notes on finished proposals | cleared after 90 days |
| Agent tasks | 400 days |
| Saved weekly client reports | 400 days |
| Daily limit counters | 35 days |
Pending, approved and executing proposals are never deleted by retention.
Availability
| Surface | Status |
|---|---|
REST API with an API key (/v1/proposals, /v1/activity, /v1/agent-tasks, /v1/websites) | Available. |
API-key MCP endpoint (mcp.rankparse.com) | Available. It has the propose, task and activity tools. |
Secure OAuth connector for Claude and ChatGPT (connect.rankparse.com) | Read-only. It can list your websites and your inbox proposals. Letting an agent put drafts in your inbox through the connector is planned but not available yet. |
| Give your agent a task box and stored tasks | Only on accounts where agent proposals are available. Elsewhere the box opens Claude or ChatGPT with the prompt pre-filled and nothing is stored. |
If the inbox has not been switched on for an account, POST /v1/proposals returns 403 approval_inbox_not_enabled and launches and submissions behave as they did before the inbox existed.
End-to-end example
An agent wants to tell Bing and Yandex about two changed pages on example.com.
Find the website
curl "https://api.rankparse.com/v1/websites" -H "X-API-Key: rp_your_key"{ "websites": [{ "id": "site_abc123", "host": "example.com", "name": "Example" }] }Make sure the host has an IndexNow key
Provision the key, then have the person host the key file at the returned key_location. This is free. See IndexNow.
curl -X POST "https://api.rankparse.com/v1/indexnow/key?domain=example.com" \
-H "X-API-Key: rp_your_key"Propose the submission
curl -X POST "https://api.rankparse.com/v1/proposals" \
-H "X-API-Key: rp_your_key" \
-H "Content-Type: application/json" \
-d '{
"kind": "indexnow_submit",
"site_id": "site_abc123",
"urls": ["https://example.com/blog/new-post", "https://example.com/pricing"],
"note": "Published a new post and changed the pricing page."
}'import requests
H = {"X-API-Key": "rp_your_key"}
res = requests.post(
"https://api.rankparse.com/v1/proposals",
headers=H,
json={
"kind": "indexnow_submit",
"site_id": "site_abc123",
"urls": ["https://example.com/blog/new-post", "https://example.com/pricing"],
"note": "Published a new post and changed the pricing page.",
},
)
proposal = res.json()
print(proposal["status"], proposal["review_url"])const H = { "X-API-Key": "rp_your_key", "Content-Type": "application/json" };
const res = await fetch("https://api.rankparse.com/v1/proposals", {
method: "POST",
headers: H,
body: JSON.stringify({
kind: "indexnow_submit",
site_id: "site_abc123",
urls: ["https://example.com/blog/new-post", "https://example.com/pricing"],
note: "Published a new post and changed the pricing page.",
}),
});
const proposal = await res.json();
console.log(proposal.status, proposal.review_url);{
"status": "awaiting_approval",
"proposal_id": "prp_V1StGXR8_Z5jdHi6B-myT",
"review_url": "https://rankparse.com/dashboard/sites/site_abc123/today?proposal=prp_V1StGXR8_Z5jdHi6B-myT",
"title": "Submit 2 URLs on example.com to IndexNow",
"dedupe_hit": false,
"message": "Waiting for the user's approval in RankParse: ..."
}Ask the person to approve
The agent tells the person: "I've queued two pages for IndexNow. Review and approve here: the review_url." The person opens it, checks the URLs and approves. Nothing has been submitted and no credit has been spent yet.
Read the outcome
curl "https://api.rankparse.com/v1/proposals/prp_V1StGXR8_Z5jdHi6B-myT" \
-H "X-API-Key: rp_your_key"{
"proposal": {
"id": "prp_V1StGXR8_Z5jdHi6B-myT",
"kind": "indexnow_submit",
"status": "succeeded",
"title": "Submit 2 URLs on example.com to IndexNow",
"site_id": "site_abc123",
"source": "agent",
"estimated_credits": 1,
"created_at": 1790000000000,
"expires_at": 1790604800000,
"decided_at": 1790003600000,
"decided_via": "web",
"result": { "host": "example.com", "url_count": 2, "key_location": "https://example.com/4f9c2a7e1b3d4c8aa0e6.txt" },
"error_code": null
}
}While it is pending, keep waiting or stop. Do not propose it again: an identical proposal returns the same item.
Log what you did
curl -X POST "https://api.rankparse.com/v1/activity" \
-H "X-API-Key: rp_your_key" \
-H "Content-Type: application/json" \
-d '{"summary": "Proposed IndexNow submission for 2 changed pages.", "site_id": "site_abc123"}'Troubleshooting
Related
MCP Server
Connect RankParse to Claude, ChatGPT and developer MCP clients. Two endpoints, a full tool catalog, and how to fix common errors.
Outreach
Run AI-driven link-building outreach from your own Gmail. Your agent finds prospects and writes every email, you approve, and RankParse sends on a schedule.