Spaces:
Running
A newer version of the Gradio SDK is available:
5.49.1
Piclets Discovery Server API Documentation
Overview
The Piclets Discovery Server provides a Gradio-based API for the Piclets discovery game. Each real-world object has ONE canonical Piclet, with variations tracked based on attributes. All data is stored in a public HuggingFace Dataset.
Quick Start
Running Locally
pip install -r requirements.txt
python app.py
Accessing the API
- Web Interface: http://localhost:7860
- Programmatic Access: Use Gradio Client to connect to the space
Frontend Integration
import { Client } from "@gradio/client";
const client = await Client.connect("Fraser/piclets-server");
const result = await client.predict("/search_piclet", {
object_name: "pillow",
attributes: ["velvet"]
});
API Endpoints
1. Search Piclet
Endpoint: /search_piclet
Purpose: Search for canonical Piclet or variations
Method: Gradio function call
Input Parameters:
{
"object_name": "pillow",
"attributes": ["velvet", "blue"]
}
Response Types:
New Object (no Piclet exists):
{
"status": "new",
"message": "No Piclet found for 'pillow'",
"piclet": null
}
Existing Canonical (exact match):
{
"status": "existing",
"message": "Found canonical Piclet for 'pillow'",
"piclet": {
"objectName": "pillow",
"typeId": "pillow_canonical",
"discoveredBy": "user123",
"discoveredAt": "2024-07-26T10:30:00",
"scanCount": 42,
"picletData": { /* full Piclet data */ }
}
}
Variation Found:
{
"status": "variation",
"message": "Found variation of 'pillow'",
"piclet": { /* variation data */ },
"canonicalId": "pillow_canonical"
}
New Variation Suggested:
{
"status": "new_variation",
"message": "No variation found for 'pillow' with attributes ['velvet', 'blue']",
"canonicalId": "pillow_canonical",
"piclet": null
}
2. Create Canonical
Endpoint: /create_canonical
Purpose: Register the first discovery of an object with OAuth verification
Method: Gradio function call
Input Parameters:
{
"object_name": "pillow",
"piclet_data": "{ /* JSON string of Piclet instance */ }",
"token_or_username": "hf_xxxxxxxxxxxxx" // OAuth token or username for testing
}
Success Response:
{
"success": true,
"message": "Created canonical Piclet for 'pillow'",
"piclet": {
"objectName": "pillow",
"typeId": "pillow_canonical",
"discoveredBy": "username123",
"discovererSub": "987654321",
"discovererUsername": "username123",
"discovererName": "Display Name",
"discovererPicture": "/static-proxy?url=https%3A%2F%2Favatars.huggingface.co%2F...",
"discoveredAt": "2024-07-26T10:30:00",
"scanCount": 1,
"picletData": { /* full Piclet data */ }
}
}
Error Responses:
{
"success": false,
"error": "Invalid OAuth token"
}
{
"success": false,
"error": "Failed to save canonical Piclet"
}
Notes:
- If
token_or_usernamestarts withhf_, it's verified as an OAuth token - Token verification calls
https://huggingface.co/oauth/userinfo - User profile is created/updated with cached OAuth fields
- Legacy mode: Plain usernames create
legacy_{username}profiles
3. Create Variation
Endpoint: /create_variation
Purpose: Add a variation to an existing canonical Piclet with OAuth verification
Method: Gradio function call
Input Parameters:
{
"canonical_id": "pillow_canonical",
"attributes": ["velvet", "blue"],
"piclet_data": "{ /* JSON string of variation data */ }",
"token_or_username": "hf_xxxxxxxxxxxxx", // OAuth token or username for testing
"object_name": "pillow"
}
Success Response:
{
"success": true,
"message": "Created variation of 'pillow'",
"piclet": {
"typeId": "pillow_001",
"attributes": ["velvet", "blue"],
"discoveredBy": "player456",
"discovererSub": "123456789",
"discovererUsername": "player456",
"discovererName": "Player Name",
"discovererPicture": "/static-proxy?url=https%3A%2F%2Favatars.huggingface.co%2F...",
"discoveredAt": "2024-07-26T11:00:00",
"scanCount": 1,
"picletData": { /* variation data */ }
}
}
Error Responses:
{
"success": false,
"error": "Invalid OAuth token"
}
{
"success": false,
"error": "Canonical Piclet not found for 'pillow'"
}
Notes:
- Same OAuth verification as create_canonical
- User profile updated with variation discovery (+50 rarity points)
- Variation numbering is automatic (pillow_001, pillow_002, etc.)
4. Increment Scan Count
Endpoint: /increment_scan_count
Purpose: Track how many times a Piclet has been discovered
Method: Gradio function call
Input Parameters:
{
"piclet_id": "pillow_canonical",
"object_name": "pillow"
}
Success Response:
{
"success": true,
"scanCount": 43
}
5. Get Recent Activity
Endpoint: /get_recent_activity
Purpose: Get global discovery feed
Method: Gradio function call
Input Parameters:
{
"limit": 20
}
Response:
{
"success": true,
"activities": [
{
"type": "discovery",
"objectName": "pillow",
"typeId": "pillow_canonical",
"discoveredBy": "user123",
"discoveredAt": "2024-07-26T10:30:00",
"scanCount": 42
},
{
"type": "variation",
"objectName": "pillow",
"typeId": "pillow_001",
"attributes": ["velvet", "blue"],
"discoveredBy": "user456",
"discoveredAt": "2024-07-26T11:00:00",
"scanCount": 5
}
]
}
6. Get Leaderboard
Endpoint: /get_leaderboard
Purpose: Get top discoverers by rarity score
Method: Gradio function call
Input Parameters:
{
"limit": 10
}
Response:
{
"success": true,
"leaderboard": [
{
"rank": 1,
"username": "explorer123",
"totalFinds": 156,
"uniqueFinds": 45,
"rarityScore": 2340
},
{
"rank": 2,
"username": "hunter456",
"totalFinds": 134,
"uniqueFinds": 38,
"rarityScore": 1890
}
]
}
7. Get User Profile
Endpoint: /get_user_profile
Purpose: Get individual user's discovery statistics
Method: Gradio function call
Input Parameters:
{
"sub": "987654321" // HuggingFace user ID (preferred) or username for legacy
}
Response:
{
"success": true,
"profile": {
"sub": "987654321",
"preferred_username": "player123",
"name": "Player Display Name",
"picture": "/static-proxy?url=https%3A%2F%2Favatars.huggingface.co%2F...",
"email": "[email protected]",
"joinedAt": "2024-07-01T10:00:00",
"lastSeen": "2024-07-26T12:00:00",
"discoveries": ["pillow_canonical", "chair_002", "lamp_canonical"],
"uniqueFinds": 2,
"totalFinds": 3,
"rarityScore": 250,
"visibility": "public"
}
}
Notes:
- Profile keyed by
sub(stable HF user ID), not username - OAuth fields (preferred_username, name, picture) cached and refreshed on each login
- Legacy profiles have
sub = "legacy_{username}" - Visibility can be "public" or "private" (future feature)
Object Normalization Rules
The server normalizes object names for consistent storage:
- Convert to lowercase
- Remove articles (the, a, an)
- Handle pluralization:
pillowsβpillowberriesβberryleavesβleafboxesβbox
- Replace spaces with underscores
- Remove special characters
Examples:
"The Blue Pillow"βpillow"wooden chairs"βwooden_chair"A pair of glasses"βpair_of_glass
Rarity Tiers
Based on scan count:
- Legendary: β€ 5 scans
- Epic: 6-20 scans
- Rare: 21-50 scans
- Uncommon: 51-100 scans
- Common: > 100 scans
Scoring System
- Canonical Discovery: +100 rarity points
- Variation Discovery: +50 rarity points
- Scan Bonus: Additional points based on rarity tier
Error Handling
All endpoints return consistent error structures:
{
"success": false,
"error": "Description of what went wrong"
}
Common error scenarios:
- Piclet not found
- Invalid JSON data
- Failed to save to dataset
- Network/connection errors
Rate Limiting
Currently no rate limiting implemented. For production:
- Consider adding per-user rate limits
- Implement cooldowns for discoveries
- Cache frequent requests
Authentication
OAuth Token Verification (Production Mode):
- Frontend sends
Authorization: Bearer <hf_token>headers - Server verifies tokens via
https://huggingface.co/oauth/userinfo - Returns user info:
sub(stable ID),preferred_username,name,picture,email - User profiles keyed by
sub(HF user ID) instead of username - Usernames can change, but
subremains stable
Legacy Mode (Testing Only):
- For backward compatibility, endpoints accept plain usernames
- If token doesn't start with
hf_, treated as username - Creates legacy user profile with
sub = "legacy_{username}"
Example OAuth Flow:
// Frontend: Get OAuth token from HuggingFace Space
import { HfInference } from "https://cdn.jsdelivr.net/npm/@huggingface/inference/+esm";
const auth = await hfAuth.signIn();
// Make authenticated request
const response = await fetch('/api/endpoint', {
headers: {
'Authorization': `Bearer ${auth.accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ /* payload */ })
});
Token Verification Process:
- Extract Bearer token from Authorization header
- Call
https://huggingface.co/oauth/userinfowith token - Verify response status 200
- Extract user info (sub, preferred_username, name, picture)
- Get or create user profile using
subas key - Cache profile fields on each request
Data Storage
All data stored in HuggingFace Dataset:
- Repository:
Fraser/piclets - Type: Public dataset
- Structure:
piclets/- Canonical and variation datausers/- User profilesmetadata/- Global statistics
Best Practices
- Always normalize object names before searching
- Check for existing Piclets before creating new ones
- Increment scan counts when rediscovering
- Cache responses on the client side
- Handle network errors gracefully
- Validate JSON data before sending
Example Workflow
- User scans an object (e.g., pillow)
- Extract object name and attributes from caption
- Search for existing Piclet
- If new:
- Create canonical Piclet
- Award discovery bonus
- If variation:
- Create or retrieve variation
- Update scan count
- Update user profile
- Refresh activity feed
Support
For issues or questions:
- Check CLAUDE.md for implementation details
- Review example code in app.py
- Open an issue in the repository