Skip to main content

Overview

The ratings system allows users to provide feedback on AI-generated responses via thumbs up/down ratings. Ratings are tied to wallet addresses and can be tracked per message or aggregated per agent.

Rate Message

curl -X POST https://api.example.com/ratings \
  -H "Content-Type: application/json" \
  -d '{
    "messageId": "msg-1234567890",
    "walletAddress": "0x1234...",
    "isPositive": true,
    "agentId": "oracle"
  }'
Request Body
messageId
string
required
Unique message identifier to rate
walletAddress
string
required
Wallet address of the user providing the rating
isPositive
boolean
required
true for thumbs up, false for thumbs down
agentId
string
Optional agent identifier (oracle, scout, news, yield, tokenomics, nft, perp)
{
  "success": true
}
Users can update their rating by calling this endpoint again with the same messageId and walletAddress.

Get Message Rating

curl -X GET "https://api.example.com/ratings/msg-1234567890?wallet=0x1234..."
Path Parameters
messageId
string
required
Message ID to check rating for
Query Parameters
wallet
string
required
Wallet address to check rating from
{
  "success": true,
  "rating": true
}
Response Fields
success
boolean
required
Whether the request succeeded
rating
boolean | null
required
  • true: User gave thumbs up
  • false: User gave thumbs down
  • null: User has not rated this message

Get Agent Rating

curl -X GET https://api.example.com/agent/rating
Returns the aggregate rating for all agents (or a specific agent if filtered by database query).
{
  "success": true,
  "rating": 4.7,
  "totalRatings": 1250
}
Response Fields
success
boolean
required
Whether the request succeeded
rating
number
required
Average rating score (0.0 to 5.0 scale)
totalRatings
number
required
Total number of ratings received

Get Average Response Time

curl -X GET https://api.example.com/agent/response-time
{
  "success": true,
  "avgResponseTimeMs": 1450
}
Response Fields
avgResponseTimeMs
number
required
Average response time in milliseconds across all queries

Get Usage Count

curl -X GET https://api.example.com/agent/usage-count
{
  "success": true,
  "usageCount": 5432
}
Response Fields
usageCount
number
required
Total number of queries processed

Get Agent Stats (Dashboard)

curl -X GET "https://api.example.com/dashboard/stats?agentId=oracle"
Query Parameters
agentId
string
Optional agent ID to filter stats. Omit for aggregate stats.
{
  "agentId": "oracle",
  "agentName": "Price Oracle Agent",
  "wallet": "0x5678...",
  "treasury": "45.32",
  "tasksCompleted": 1234,
  "rating": 4.8,
  "totalRatings": 856,
  "avgResponseTime": "0.8s",
  "isFrozen": false
}
{
  "treasury": "150.50",
  "tasksCompleted": 5432,
  "isFrozen": false
}
Response Fields (Agent-Specific)
agentId
string
Agent identifier
agentName
string
Human-readable agent name
wallet
string
Agent’s payment wallet address
treasury
string
Current USDC balance in agent’s wallet
tasksCompleted
number
Total successful queries processed
rating
number
Average user rating (0.0-5.0)
totalRatings
number
Number of ratings received
avgResponseTime
string
Average response time (formatted as “1.5s”)
isFrozen
boolean
Whether agent is frozen by policy

Error Responses

{
  "success": false,
  "error": "Missing required fields"
}
{
  "error": "Unsupported agentId: invalid-agent"
}
{
  "error": "Database query failed"
}

Integration Example

// Submit a rating
const rateMessage = async (messageId: string, walletAddress: string, isPositive: boolean) => {
  const response = await fetch('https://api.example.com/ratings', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      messageId,
      walletAddress,
      isPositive,
      agentId: 'oracle',
    }),
  });
  return response.json();
};

// Check if user has already rated a message
const getUserRating = async (messageId: string, walletAddress: string) => {
  const response = await fetch(
    `https://api.example.com/ratings/${messageId}?wallet=${walletAddress}`
  );
  const { rating } = await response.json();
  return rating; // true, false, or null
};

// Display agent stats in dashboard
const getAgentStats = async (agentId: string) => {
  const response = await fetch(
    `https://api.example.com/dashboard/stats?agentId=${agentId}`
  );
  return response.json();
};

// Example: Rating component
const RatingButton = ({ messageId, walletAddress }: Props) => {
  const [userRating, setUserRating] = useState<boolean | null>(null);

  useEffect(() => {
    getUserRating(messageId, walletAddress).then(setUserRating);
  }, [messageId, walletAddress]);

  const handleRate = async (isPositive: boolean) => {
    await rateMessage(messageId, walletAddress, isPositive);
    setUserRating(isPositive);
  };

  return (
    <div>
      <button
        onClick={() => handleRate(true)}
        className={userRating === true ? 'active' : ''}
      >
        👍
      </button>
      <button
        onClick={() => handleRate(false)}
        className={userRating === false ? 'active' : ''}
      >
        👎
      </button>
    </div>
  );
};

Database Schema

Ratings are stored in Supabase: message_ratings table:
  • message_id (text)
  • wallet_address (text)
  • is_positive (boolean)
  • agent_id (text, nullable)
  • created_at (timestamp)
  • Composite primary key: (message_id, wallet_address)
query_performance table (for response time tracking):
  • id (uuid, primary key)
  • response_time_ms (integer)
  • agent_id (text, nullable)
  • tx_hash (text, nullable)
  • created_at (timestamp)
Ratings are immutable once submitted. To change a rating, the same endpoint is called again with updated isPositive value.

Rate Limiting

Ratings endpoints use the general rate limiter:
  • 100 requests per 15-minute window per IP
  • Browser preflight (OPTIONS) requests are exempt
  • GET endpoints (stats, response time, usage count) are exempt
Excessive rating submissions from the same wallet may be flagged as spam in future updates.

Build docs developers (and LLMs) love