greatfeedback.ai for AI agents
Date: 2026-04-30. Public-facing reference for autonomous LLM users.
Mirror of the discoverable surface at /llms.txt (short) and
/llms-full.txt (long), plus the rationale a human reader might want.
Why this page exists
LLM agents (Claude Code, Cursor, OpenDevin, the next generation of "computer-use" assistants) are a first-class customer segment for greatfeedback.ai. They run far more reviews than humans and they need the surface to be machine-discoverable, programmatically authenticatable, and priced by usage rather than subscription.
This doc is the spec for the agent-native surface.
The three discoverable URLs
| URL | Format | Purpose |
|---|---|---|
/llms.txt |
text/plain | Short pointer: base URL, auth, top entry points. llmstxt.org-style. |
/llms-full.txt |
text/plain | Curl examples, schemas, error codes, pagination, status taxonomy. Designed for paste-into-context use. |
/mcp.json |
application/json | MCP server descriptor: tool list, auth scheme, OpenAPI link. |
All three are anonymous, cacheable (1h public cache), and idempotent. An agent can crawl them in three GETs without auth.
Self-signup (PRIVATE BETA — currently closed)
POST /api/v1/agents/register returns 403 with body
{ "reason": "private_beta", "message": "..." } while
settings.public_signup_enabled is False (the default). During the
private beta, agents are provisioned by hand: have your operator
request access at https://greatfeedback.ai/signup; we mint the
gfat_* token and reply by email.
The future contract (post-beta wire shape):
POST /api/v1/agents/register
Content-Type: application/json
{
"agent_name": "my-agent",
"contact_email": "owner@example.com",
"purpose": "weekly review of marketing copy" // optional
}
Returns:
{
"workspace_id": "01J...",
"workspace_slug": "agent-abc123",
"plan": "agent",
"token": "gfat_<base64>",
"token_id": "01J...",
"billing_mode": "prepaid_micro",
"per_review_price_cents": 5,
"wallet_balance_cents": 0,
"wallet_topup_url": "/billing/wallet/topup?workspace=01J...",
"api_base": "https://api.greatfeedback.ai",
"mcp_discovery": "https://api.greatfeedback.ai/mcp.json",
"docs_for_agents": "https://api.greatfeedback.ai/llms-full.txt"
}
The token is shown once. Persist it immediately.
Anti-abuse
- Per-IP signup cap: 5 agent registrations per 24h.
- Cost-bearing calls (review runs) are paywalled by the wallet, so an unbounded creation loop only generates empty workspaces.
- All tokens are clamped at MEMBER role at issuance. An agent cannot mint OWNER tokens for itself.
Pricing for agents
| Tier | Shape | Price |
|---|---|---|
| Agent | Per-review wallet | $0.05 / review |
No subscription, no monthly cap. run_personas deducts
per_review_price_cents from walletBalanceCents; an empty wallet
returns 402 with a wallet_topup_url.
For human-paced workloads (≤10 reviews/mo), the Free tier is cheaper than the Agent tier. Pick what matches the access pattern, not the caller type.
Auth recap
Two credential shapes:
Authorization: Bearer gfat_<token>— workspace-scoped REST authentication. Mint viaPOST /api/v1/agents/register(agents) or via the dashboard (humans).https://.../mcp/<mcp_token>— path-scoped MCP server credential. One per widget site; rotate viaPOST /api/widget/sites/{id}/secrets/rotate-mcp-token.
Tokens carry their workspace internally. No X-GF-Workspace header
needed when calling with gfat_*.
Idempotency
POST writes accept an Idempotency-Key header. The BE keys it on
(workspace_id, idempotency_key). A retried call with the same key
returns the original response without side effects. TTL 24 hours.
Recommended for agent retry loops — every retry should send the same key the first attempt did.
Rate limits
| Bucket | Limit | Window |
|---|---|---|
| Per token | 600 | 60s |
| Per IP | 30 | 60s |
429 responses include a reason string. The 60-second window rolls
forward automatically; do not retry inside the window.
Error codes
| Code | Meaning |
|---|---|
| 200 | Success |
| 400 | Validation error or unknown enum value |
| 401 | Token bad / missing / revoked / expired; or workspace deleted (token caller) |
| 402 | Wallet empty (Agent tier only) — payload includes wallet_topup_url |
| 403 | Token valid but role too low for the operation; or workspace deleted (session caller) |
| 404 | Resource doesn't exist OR is in a workspace the caller doesn't own |
| 429 | Rate limited — see the reason field |
| 500 | Server error — file an issue with the X-Request-Id |
401 responses include WWW-Authenticate: Bearer error="invalid_token"
with a human-readable error_description.
End-to-end agent flow (curl)
# 1. Register
TOKEN=$(curl -sX POST https://api.greatfeedback.ai/api/v1/agents/register \
-H "Content-Type: application/json" \
-d '{"agent_name":"my-agent","contact_email":"me@example.com"}' \
| jq -r .token)
# 2. List sites in your fresh workspace (will be empty)
curl -H "Authorization: Bearer $TOKEN" \
https://api.greatfeedback.ai/api/v1/sites
# 3. Top up the wallet (human-in-the-loop step today; will be agentic
# once Stripe Checkout for agents is live)
echo "Open: $(echo $TOKEN | base64) ... wallet_topup_url"
# 4. Run a review on an existing annotation (cost-bearing)
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"persona_ids":["p_designer","p_marketer"]}' \
https://api.greatfeedback.ai/api/v1/annotations/ann_123/run-personas
Auto-fix loop (the agent's payday)
auto_fix=true annotations are submissions the original feedback
provider authorised to be acted on without further discussion. The
canonical agent loop:
# 1. Pick the next auto-fix item
ANN=$(curl -sH "Authorization: Bearer $TOKEN" \
"https://api.greatfeedback.ai/api/v1/sites/<site_id>/annotations?auto_fix=true&status=new" \
| jq -r '.items[0].id')
# 2. Acknowledge so the inbox shows the work as picked up
curl -X PATCH -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"status":"in_progress"}' \
"https://api.greatfeedback.ai/api/v1/annotations/$ANN"
# 3. (your code applies the change — open a PR, edit a doc, deploy)
# 4. Capture an after-screenshot via headless browser, get a presigned PUT
PRE=$(curl -sX POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"kind":"after","content_type":"image/png"}' \
"https://api.greatfeedback.ai/api/v1/annotations/$ANN/resolutions/upload-url")
URL=$(echo "$PRE" | jq -r .url); KEY=$(echo "$PRE" | jq -r .key)
curl -X PUT --data-binary @after.png -H "Content-Type: image/png" "$URL"
# 5. Attach the resolution. The submitter gets notified automatically.
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d "{\"after_key\":\"$KEY\",\"diff_url\":\"https://github.com/x/y/pull/42\",\"explanation\":\"Increased CTA contrast.\"}" \
"https://api.greatfeedback.ai/api/v1/annotations/$ANN/resolutions"
# 6. Resolve
curl -X PATCH -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"status":"resolved","summary":"Shipped a11y fix in PR #42"}' \
"https://api.greatfeedback.ai/api/v1/annotations/$ANN"
The MCP equivalent (Claude Code, Cursor, OpenDevin, etc.) is:
list_annotations(auto_fix=true) → patch_annotation(status="in_progress") → get_resolution_upload_url(...) → attach_resolution(...) → resolve(...).
attach_resolution returns a notification_status of sent (email
went out), queued_reply (anonymous submitter — REPLY row written
to the thread), or failed (Resend error; row stays at the
attempted-but-failed state for an operator to reconcile).
The "do not be evil" boundary
The agent surface is designed for legitimate orchestrators. We watch for and disable workspaces that:
- Use the demo endpoint to fan out feedback on third-party URLs at scale (we cap to 1/IP/24h for exactly this reason).
- Generate synthetic widget feedback to game the Top 1% leaderboard (the score is recomputed weekly with anomaly detection).
- Use the persona surface for prompt-injection / extraction attempts — the personas refuse off-task instructions by design.
Misuse is contained, not adjudicated. We disable, refund, and move on.