Potato API Reference¶
Potato's HTTP API. Use it to drive Potato from a custom frontend, an automation script, or another system.
Overview¶
Base URL¶
http://localhost:8000
Authentication¶
Most endpoints require an active session. Sessions are established via the login endpoints and maintained via cookies.
For programmatic access, you can: 1. Use session cookies from a browser 2. Use the debug mode with automatic user creation 3. Implement the login flow programmatically
Response Format¶
All API endpoints return JSON responses. Error responses include an error field with a description.
Session Management¶
Login¶
POST /auth
Content-Type: application/x-www-form-urlencoded
Request Body:
username=your_username&password=your_password
Response: Redirects to annotation page on success, or returns error.
Check Session¶
GET /api/current_instance
Response (authenticated):
{
"instance_id": "item_001",
"current_index": 0,
"total_instances": 100
}
Response (not authenticated):
{
"error": "No active session"
}
Logout¶
POST /logout
Response: Redirects to home page.
Annotation Endpoints¶
Get Current Instance¶
GET /api/current_instance
Returns information about the user's current annotation instance.
Response:
{
"instance_id": "item_001",
"current_index": 5,
"total_instances": 100
}
Get Instance Content¶
GET /api/spans/{instance_id}
Returns the text content and existing span annotations for an instance.
Response:
{
"instance_id": "item_001",
"text": "The quick brown fox jumps over the lazy dog.",
"spans": [
{
"id": "span_123",
"schema": "entities",
"label": "ANIMAL",
"title": "ANIMAL",
"start": 16,
"end": 19,
"text": "fox",
"color": "#ff6b6b"
}
]
}
Get Annotations¶
GET /get_annotations?instance_id={instance_id}
Returns all annotations (labels and spans) for a specific instance.
Response:
{
"label_annotations": {
"sentiment": {
"positive": "1"
}
},
"span_annotations": {
"entities:ANIMAL:16:19": "true"
}
}
Submit Annotation¶
POST /updateinstance
Content-Type: application/json
Submit or update annotations for an instance.
Request Body (Frontend Format):
{
"instance_id": "item_001",
"annotations": {
"sentiment:positive": "1",
"sentiment:negative": "0"
},
"span_annotations": [
{
"schema": "entities",
"name": "PERSON",
"title": "PERSON",
"start": 0,
"end": 5,
"value": "true"
}
],
"client_timestamp": "2024-01-15T10:30:00Z"
}
Each key in annotations names a schema and a label in one flat string:
schema:::label, or schema:label. Both are read; the browser sends the
three-colon form, and a label whose own name contains a colon needs it.
The value is the answer for that label, not a container. This nests the label under the schema and so names no label at all:
{"annotations": {"sentiment": {"positive": "1"}}}
Nothing is stored for it. That is the shape annotations are stored in, which
makes it the natural first guess. A request where no key can be read is
refused with 400 listing the keys it could not read.
Request Body (Backend Format):
{
"instance_id": "item_001",
"schema": "sentiment",
"type": "label",
"state": [
{"name": "positive", "value": "1"},
{"name": "negative", "value": "0"}
]
}
Response (Success):
{
"status": "success",
"processing_time_ms": 15,
"performance_metrics": {
"total_annotations": 50,
"session_duration": 1800
}
}
Response (With Quality Control Feedback):
{
"status": "success",
"processing_time_ms": 12,
"qc_result": {
"type": "gold_standard",
"correct": false,
"gold_label": {"sentiment": "positive"},
"explanation": "Strong positive language indicates positive sentiment."
}
}
Response (Attention Check Warning):
{
"status": "success",
"warning": true,
"warning_message": "Please read items carefully before answering.",
"qc_result": {
"type": "attention_check",
"passed": false,
"warning": true
}
}
Response (Blocked):
{
"status": "blocked",
"message": "You have been blocked due to too many incorrect responses."
}
Clear Span Annotations¶
POST /api/spans/{instance_id}/clear
Clears all span annotations for an instance.
Response:
{
"status": "success",
"cleared_count": 3
}
Navigate to Instance¶
POST /go_to
Content-Type: application/json
Navigate to a specific instance by ID or index.
Request Body:
{
"go_to": "item_005"
}
Or by action:
{
"action": "next_instance"
}
Schema Information¶
Get Annotation Schemas¶
GET /api/schemas
Returns information about configured annotation schemas (primarily for span annotations).
Response:
{
"entities": {
"name": "entities",
"description": "Named entity recognition",
"labels": ["PERSON", "ORGANIZATION", "LOCATION"],
"type": "span"
},
"sentiment_spans": {
"name": "sentiment_spans",
"description": "Sentiment-bearing phrases",
"labels": ["positive", "negative"],
"type": "span"
}
}
Get Label Colors¶
GET /api/colors
Returns the color mapping for annotation labels.
Response:
{
"entities": {
"PERSON": "#ff6b6b",
"ORGANIZATION": "#4ecdc4",
"LOCATION": "#45b7d1"
}
}
Get Keyword Highlights¶
GET /api/keyword_highlights/{instance_id}
Returns admin-defined keyword matches found in the instance text. Keywords are configured via keyword_highlights_file in the config.
Parameters:
- instance_id (path): The ID of the instance to get keyword highlights for
Response:
{
"instance_id": "item_1",
"keywords": [
{
"label": "positive",
"start": 10,
"end": 19,
"text": "excellent",
"reasoning": "Keyword: excel* → positive",
"schema": "sentiment",
"color": "rgba(34, 197, 94, 0.8)"
},
{
"label": "negative",
"start": 45,
"end": 53,
"text": "terrible",
"reasoning": "Keyword: terrible → negative",
"schema": "sentiment",
"color": "rgba(239, 68, 68, 0.8)"
}
]
}
Response Fields:
| Field | Description |
|-------|-------------|
| instance_id | The instance ID |
| keywords | Array of keyword matches found in the text |
| keywords[].label | The label associated with this keyword |
| keywords[].start | Character offset where the match starts |
| keywords[].end | Character offset where the match ends |
| keywords[].text | The actual matched text from the instance |
| keywords[].reasoning | Description of the keyword pattern that matched |
| keywords[].schema | The annotation schema this keyword belongs to |
| keywords[].color | RGBA color string for rendering the highlight |
Notes:
- Returns empty keywords array if no keyword_highlights_file is configured
- Keywords are sorted by start position
- Duplicate matches at the same position are deduplicated
- Colors are taken from ui.spans.span_colors config or auto-assigned
Admin API Endpoints¶
Admin endpoints require admin privileges or API key authentication.
Health Check¶
GET /admin/health
Response:
{
"status": "healthy",
"timestamp": "2024-01-15T10:30:00Z",
"version": "2.0.0"
}
Dashboard Overview¶
GET /admin/api/overview
Response:
{
"total_items": 1000,
"total_annotations": 5000,
"total_users": 25,
"active_users": 10,
"completion_rate": 0.45,
"items_by_status": {
"completed": 450,
"in_progress": 150,
"unassigned": 400
}
}
Get Annotators¶
GET /admin/api/annotators
Response:
{
"annotators": [
{
"user_id": "user1",
"annotations_count": 200,
"current_phase": "annotation",
"last_active": "2024-01-15T10:30:00Z",
"assigned_items": 250,
"completed_items": 200
}
],
"total_count": 25
}
Get Instances¶
GET /admin/api/instances
Query Parameters:
- status - Filter by status (completed, in_progress, unassigned)
- limit - Maximum number of results (default: 100)
- offset - Pagination offset
Response:
{
"instances": [
{
"id": "item_001",
"text_preview": "The quick brown fox...",
"annotations_count": 3,
"status": "completed"
}
],
"total_count": 1000
}
Get Configuration¶
GET /admin/api/config
Response:
{
"annotation_task_name": "Sentiment Analysis",
"annotation_schemes": [...],
"total_items": 1000,
"output_format": "json"
}
Update Configuration¶
POST /admin/api/config
Content-Type: application/json
Request Body:
{
"setting_name": "value"
}
Get Annotation History¶
GET /admin/api/annotation_history
Query Parameters:
- user_id - Filter by user
- instance_id - Filter by instance
- minutes - Time window in minutes
Response:
{
"history": [
{
"user_id": "user1",
"instance_id": "item_001",
"action_type": "add_label",
"schema_name": "sentiment",
"label_name": "positive",
"timestamp": "2024-01-15T10:30:00Z"
}
]
}
Get Suspicious Activity¶
GET /admin/api/suspicious_activity
Response:
{
"suspicious_users": [
{
"user_id": "user5",
"flags": ["rapid_submissions", "low_time_per_item"],
"avg_time_per_item": 2.5,
"annotations_count": 500
}
]
}
Get Crowdsourcing Data¶
GET /admin/api/crowdsourcing
Response:
{
"summary": {
"total_workers": 50,
"prolific_workers": 30,
"mturk_workers": 15,
"other_workers": 5
},
"prolific": {
"workers": [...],
"completion_codes_issued": 28
},
"mturk": {
"workers": [...],
"hits_completed": 15
}
}
Quality Control API¶
Get Quality Control Metrics¶
GET /admin/api/quality_control
Response:
{
"enabled": true,
"attention_checks": {
"enabled": true,
"total_items": 5,
"total_checks": 150,
"total_passed": 140,
"total_failed": 10,
"by_user": {
"user1": {
"passed": 10,
"failed": 0,
"pass_rate": 1.0
},
"user2": {
"passed": 8,
"failed": 2,
"pass_rate": 0.8
}
}
},
"gold_standards": {
"enabled": true,
"total_items": 10,
"total_evaluations": 200,
"total_correct": 170,
"total_incorrect": 30,
"by_user": {
"user1": {
"correct": 9,
"total": 10,
"accuracy": 0.9
}
},
"by_item": {
"gold_001": {
"correct": 18,
"total": 20,
"accuracy": 0.9
}
}
},
"auto_promotion": {
"enabled": true,
"min_annotators": 3,
"agreement_threshold": 1.0,
"promoted_count": 5,
"promoted_items": [
{
"item_id": "item_042",
"consensus_label": {"sentiment": "positive"},
"annotator_count": 3,
"promoted_at": "2024-01-15T10:30:00Z"
}
],
"candidates": [
{
"item_id": "item_055",
"annotator_count": 2,
"needed_annotators": 3,
"schema_agreement": {
"sentiment": {
"value": "negative",
"count": 2,
"total": 2,
"agreement": 1.0
}
}
}
]
},
"pre_annotation": {
"enabled": true,
"items_with_predictions": 1000
}
}
Get Agreement Metrics¶
GET /admin/api/agreement
Response:
{
"enabled": true,
"overall": {
"average_krippendorff_alpha": 0.78,
"schemas_evaluated": 2,
"interpretation": "Tentative agreement"
},
"by_schema": {
"sentiment": {
"krippendorff_alpha": 0.82,
"metric_type": "nominal",
"items_evaluated": 100,
"total_annotations": 300,
"interpretation": "Good agreement"
},
"intensity": {
"krippendorff_alpha": 0.74,
"metric_type": "interval",
"items_evaluated": 100,
"total_annotations": 300,
"interpretation": "Tentative agreement"
}
},
"warnings": []
}
AI Assistant API¶
Get AI Suggestion¶
GET /get_ai_suggestion?annotationId={annotation_index}&aiAssistant={ai_assistant_type}
Response:
{
"suggestion": "Based on the text, this appears to be positive sentiment.",
"confidence": 0.85,
"labels": {
"sentiment": "positive"
}
}
Get AI Assistant Help¶
GET /api/ai_assistant?instance_id={instance_id}&schema={schema_name}
Response:
{
"html": "<div class='ai-hint'>This text expresses positive sentiment...</div>",
"suggestions": [
{
"schema": "sentiment",
"label": "positive",
"confidence": 0.9
}
]
}
User State Endpoints (Admin)¶
Get User State¶
GET /admin/user_state/{user_id}
Response:
{
"user_id": "user1",
"current_phase": "annotation",
"current_instance_index": 45,
"instance_id_ordering": ["item_001", "item_002", ...],
"assigned_count": 100,
"completed_count": 45,
"annotation_history": [...]
}
Get All Users¶
GET /admin/system_state
Response:
{
"users": {
"user1": {
"phase": "annotation",
"annotations": 200,
"last_active": "2024-01-15T10:30:00Z"
}
},
"items": {
"total": 1000,
"assigned": 800,
"completed": 500
}
}
Item State Endpoints (Admin)¶
Get All Items¶
GET /admin/all_instances
Response:
{
"instances": [
{
"id": "item_001",
"text": "The quick brown fox...",
"assigned_to": ["user1", "user2"],
"annotations_count": 2
}
]
}
Get Item State¶
GET /admin/item_state/{item_id}
Response:
{
"id": "item_001",
"text": "The quick brown fox jumps over the lazy dog.",
"data": {
"id": "item_001",
"text": "The quick brown fox jumps over the lazy dog.",
"metadata": {...}
},
"assigned_to": ["user1", "user2"],
"annotations": {
"user1": {
"sentiment": {"positive": "1"}
},
"user2": {
"sentiment": {"positive": "1"}
}
}
}
Media Endpoints¶
Get Audio Waveform¶
GET /api/waveform/{cache_key}
Returns cached waveform data for audio annotation.
Generate Audio Waveform¶
POST /api/waveform/generate
Content-Type: application/json
Request Body:
{
"audio_url": "https://example.com/audio.mp3"
}
Response:
{
"cache_key": "abc123",
"waveform_url": "/api/waveform/abc123"
}
Proxy Audio¶
GET /api/audio/proxy?url={encoded_audio_url}
Proxies external audio files to handle CORS issues.
Get Video Metadata¶
POST /api/video/metadata
Content-Type: application/json
Request Body:
{
"video_url": "https://example.com/video.mp4"
}
Response:
{
"duration": 120.5,
"width": 1920,
"height": 1080,
"fps": 30
}
Behavioral Tracking API¶
Track Interactions¶
POST /api/track_interactions
Content-Type: application/json
Records batched interaction events from the frontend (mouse clicks, focus time, scroll depth).
Track AI Usage¶
POST /api/track_ai_usage
Content-Type: application/json
Records AI assistance requests, responses, and user decisions for analytics.
Track Annotation Change¶
POST /api/track_annotation_change
Content-Type: application/json
Records annotation changes from the frontend (select, deselect, update, clear actions).
Get Behavioral Data¶
GET /api/behavioral_data/{instance_id}
Returns behavioral data for a specific instance (interaction events, timing, AI usage).
Option Highlighting API¶
Get Option Highlighting Config¶
GET /api/option_highlights/config
Returns the option highlighting configuration for AI-suggested labels.
Trigger Option Highlight Prefetch¶
POST /api/option_highlights/prefetch
Triggers prefetching of option highlights for upcoming items.
Get Option Highlights¶
GET /api/option_highlights/{annotation_id}
Returns AI-suggested option highlights for a specific annotation scheme index.
Entity Linking API¶
Search Knowledge Base¶
GET /api/entity_linking/search?query={query}&kb={kb_name}
Searches a configured knowledge base for entities matching the query.
Get Entity Details¶
GET /api/entity_linking/entity/{kb_name}/{entity_id}
Returns detailed information about a specific entity from a knowledge base.
Get Configured Knowledge Bases¶
GET /api/entity_linking/configured_kbs
Returns the list of configured knowledge bases.
Update Span with Entity Link¶
POST /api/entity_linking/update_span
Content-Type: application/json
Updates a span annotation with entity linking information.
Link and Event Annotation API¶
Get Links¶
GET /api/links/{instance_id}
Returns link annotations (span relationships) for a specific instance.
Delete Link¶
DELETE /api/links/{instance_id}/{link_id}
Deletes a specific link annotation.
Get Events¶
GET /api/events/{instance_id}
Returns event annotations for a specific instance.
Delete Event¶
DELETE /api/events/{instance_id}/{event_id}
Deletes a specific event annotation.
Span API¶
Get Span Data¶
GET /api/spans/{instance_id}
Returns text content and existing span annotations for an instance.
Clear Spans¶
DELETE /api/spans/{instance_id}/clear
Clears all span annotations for an instance.
Get Span Colors¶
GET /api/colors
Returns the color mapping for span labels.
Chat Support API¶
Send Chat Message¶
POST /api/chat/send
Content-Type: application/json
Sends a message to the LLM chat assistant and returns the response.
Get Chat History¶
GET /api/chat/history?instance_id={instance_id}
Returns chat history for a specific instance.
Get Chat Config¶
GET /api/chat/config
Returns chat UI configuration.
Agent Chat API¶
Send Agent Message¶
POST /agent_chat/send
Content-Type: application/json
Sends a message to the agent and returns a response.
Finish Agent Chat¶
POST /agent_chat/finish
Finishes the chat and writes conversation data to the item.
Get Agent Chat Status¶
GET /agent_chat/status
Returns the current agent chat session status (for page refresh recovery).
ICL Labeling API (Admin)¶
Get ICL Status¶
GET /admin/api/icl/status
Returns ICL labeler status and statistics.
Get ICL Examples¶
GET /admin/api/icl/examples?schema={schema_name}
Returns current high-confidence examples, optionally filtered by schema.
Get ICL Predictions¶
GET /admin/api/icl/predictions?schema={schema_name}&status={status}&limit={limit}
Returns LLM predictions with filtering options.
Get ICL Accuracy¶
GET /admin/api/icl/accuracy
Returns accuracy metrics for ICL labeling.
Trigger ICL Operation¶
POST /admin/api/icl/trigger
Content-Type: application/json
Request Body:
{
"action": "refresh_examples | batch_label | save_state"
}
Record ICL Verification¶
POST /api/icl/record_verification
Content-Type: application/json
Records human verification of an LLM prediction.
Adjudication API¶
Get Adjudication Queue¶
GET /adjudicate/api/queue
Returns the adjudication queue (items needing adjudication).
Get Adjudication Item¶
GET /adjudicate/api/item/{instance_id}
Returns full item detail for adjudication review.
Submit Adjudication Decision¶
POST /adjudicate/api/submit
Content-Type: application/json
Submits an adjudication decision.
Get Adjudication Stats¶
GET /adjudicate/api/stats
Returns adjudication progress statistics.
Skip Adjudication Item¶
POST /adjudicate/api/skip/{instance_id}
Skips an adjudication item.
Get Next Adjudication Item¶
GET /adjudicate/api/next
Returns the next adjudication item in the queue.
Get Similar Items¶
GET /adjudicate/api/similar/{instance_id}
Returns similar items for a specific instance (lazy-loading).
Admin Adjudication Overview¶
GET /admin/api/adjudication
Returns admin dashboard overview of adjudication status.
BWS / IBWS Scoring API (Admin)¶
Get BWS Scoring Status¶
GET /admin/api/bws_scoring
Returns current BWS (Best-Worst Scaling) scoring status and cached scores.
Generate BWS Scores¶
POST /admin/api/bws_scoring/generate
Generates BWS scores from current annotations.
Get IBWS Status¶
GET /admin/api/ibws_status
Returns current IBWS (Iterative Best-Worst Scaling) round status and progress.
Get IBWS Ranking¶
GET /admin/api/ibws_ranking
Returns current IBWS ordinal ranking.
MACE API (Admin)¶
Get MACE Overview¶
GET /admin/api/mace/overview
Returns MACE (Multiple Annotator Competence Estimation) results overview.
Get MACE Predictions¶
GET /admin/api/mace/predictions?schema={schema_name}&instance_id={instance_id}
Returns MACE predicted labels, optionally filtered by schema and instance.
Trigger MACE Computation¶
POST /admin/api/mace/trigger
Manually triggers a MACE recomputation.
Embedding Visualization API (Admin)¶
Get Visualization Data¶
GET /admin/api/embedding_viz/data
Returns visualization data for the embedding scatter plot.
Reorder Queue from Embeddings¶
POST /admin/api/embedding_viz/reorder
Content-Type: application/json
Reorders the annotation queue based on selected instances in the visualization.
Refresh Embeddings¶
POST /admin/api/embedding_viz/refresh
Forces re-computation of embeddings and UMAP projection.
Get Embedding Stats¶
GET /admin/api/embedding_viz/stats
Returns embedding visualization statistics.
Export API (Admin)¶
List Export Formats¶
GET /admin/api/export/formats
Returns available export formats with metadata.
Run Export¶
POST /admin/api/export
Content-Type: application/json
Runs an export in the requested format and returns the result.
Admin Analytics API¶
Get Behavioral Analytics¶
GET /admin/api/behavioral_analytics
Returns behavioral analytics data for all annotators (AI usage, interaction types, suspicion scores).
Get Stale Assignments¶
GET /admin/api/stale_assignments
Returns a list of stale instance assignments (assigned but not annotated past timeout).
Reclaim Instance¶
POST /admin/api/reclaim_instance
Content-Type: application/json
Manually reclaims a specific instance assignment from a user.
Set User Instances¶
POST /admin/api/user/{username}/set_instances
Content-Type: application/json
Sets the maximum number of instances for a specific user.
Get Question Analytics¶
GET /admin/api/questions
Returns aggregate analysis data for all annotation schemas/questions.
Schema API¶
Get Annotation Schemas¶
GET /api/schemas
Returns annotation schema information for the current configuration.
Error Responses¶
All endpoints may return error responses in the following format:
{
"error": "Description of the error"
}
Common HTTP status codes:
- 400 - Bad Request (invalid parameters)
- 401 - Unauthorized (no session or invalid credentials)
- 403 - Forbidden (insufficient permissions)
- 404 - Not Found (resource doesn't exist)
- 500 - Internal Server Error
Example: Complete Annotation Flow¶
Here's an example of a complete annotation flow using the API:
import requests
BASE_URL = "http://localhost:8000"
session = requests.Session()
# 1. Login
session.post(f"{BASE_URL}/auth", data={
"username": "annotator1",
"password": "password123"
})
# 2. Get current instance
response = session.get(f"{BASE_URL}/api/current_instance")
instance_info = response.json()
instance_id = instance_info["instance_id"]
# 3. Get instance content
response = session.get(f"{BASE_URL}/api/spans/{instance_id}")
content = response.json()
print(f"Text: {content['text']}")
# 4. Submit annotation
response = session.post(f"{BASE_URL}/updateinstance", json={
"instance_id": instance_id,
"annotations": {
"sentiment:positive": "1"
}
})
result = response.json()
print(f"Status: {result['status']}")
# 5. Navigate to next instance
session.post(f"{BASE_URL}/go_to", json={
"action": "next_instance"
})
# 6. Repeat steps 2-5 until done
Example: Admin Monitoring¶
import requests
BASE_URL = "http://localhost:8000"
# Get overview
overview = requests.get(f"{BASE_URL}/admin/api/overview").json()
print(f"Progress: {overview['completion_rate']*100:.1f}%")
# Get annotator stats
annotators = requests.get(f"{BASE_URL}/admin/api/annotators").json()
for a in annotators["annotators"]:
print(f"{a['user_id']}: {a['completed_items']}/{a['assigned_items']}")
# Get agreement metrics
agreement = requests.get(f"{BASE_URL}/admin/api/agreement").json()
print(f"Agreement: α = {agreement['overall']['average_krippendorff_alpha']:.3f}")
# Get quality control metrics
qc = requests.get(f"{BASE_URL}/admin/api/quality_control").json()
if qc["attention_checks"]["enabled"]:
pass_rate = qc["attention_checks"]["total_passed"] / qc["attention_checks"]["total_checks"]
print(f"Attention check pass rate: {pass_rate*100:.1f}%")
WebSocket Events (Future)¶
Currently, Potato uses polling for real-time updates. WebSocket support may be added in future versions for: - Real-time annotation updates - Live progress notifications - Collaborative annotation features