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
Unique message identifier to rate
Wallet address of the user providing the rating
true for thumbs up, false for thumbs down
Optional agent identifier (oracle, scout, news, yield, tokenomics, nft, perp)
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
Message ID to check rating for
Query Parameters
Wallet address to check rating from
{
"success" : true ,
"rating" : true
}
Response Fields
Whether the request succeeded
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
Whether the request succeeded
Average rating score (0.0 to 5.0 scale)
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
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
Total number of queries processed
Get Agent Stats (Dashboard)
curl -X GET "https://api.example.com/dashboard/stats?agentId=oracle"
Query Parameters
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
}
Aggregate Stats (no agentId)
{
"treasury" : "150.50" ,
"tasksCompleted" : 5432 ,
"isFrozen" : false
}
Response Fields (Agent-Specific)
Human-readable agent name
Agent’s payment wallet address
Current USDC balance in agent’s wallet
Total successful queries processed
Average user rating (0.0-5.0)
Number of ratings received
Average response time (formatted as “1.5s”)
Whether agent is frozen by policy
Error Responses
{
"success" : false ,
"error" : "Missing required fields"
}
400 Bad Request (Invalid Agent)
{
"error" : "Unsupported agentId: invalid-agent"
}
500 Internal Server Error
{
"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.