Skip to content

PikoClaw API Reference — all 11 endpoints with examples

API Reference

Complete documentation of all PikoClaw API endpoints. The API is a REST service deployed on Cloudflare Workers with SQLite (local) or D1 (production) storage.


Base URL

  • Local Developmenthttp://localhost:8000
  • Production (Cloudflare Workers)https://api.pappas.work

Authentication

PikoClaw uses no authentication in the current version. All endpoints are public. Production deployments should add:

// Example: Cloudflare Workers middleware
export async function withAuth(request: Request): Promise<boolean> {
    const token = request.headers.get('Authorization')?.replace('Bearer ', '');
    if (!token || !VALID_TOKENS.includes(token)) {
        return false;
    }
    return true;
}

Global Response Format

All endpoints return JSON with optional error details:

interface ApiResponse<T> {
    status: 'ok' | 'error';
    data?: T;
    error?: {
        code: string;     // e.g., 'NOT_FOUND', 'INVALID_QUERY'
        message: string;
    };
    timestamp: string;    // ISO 8601
}

Endpoints

1. Health Check

GET /health

Verify the API is running and responsive.

Request:

curl -X GET http://localhost:8000/health

Response (200 OK):

{
  "status": "ok",
  "data": {
    "version": "0.5.0",
    "uptime_ms": 123456,
    "environment": "development"
  },
  "timestamp": "2026-03-27T14:32:15Z"
}


2. List Contacts

GET /contacts

Retrieve all contacts extracted from the email archive.

Query Parameters: - limit (integer, optional, default=100) — Max results - offset (integer, optional, default=0) — Pagination offset - sort (string, optional, default=frequency) — Sort by: frequency, name, last_seen - search (string, optional) — Filter by name/email substring

Request:

curl -X GET 'http://localhost:8000/contacts?limit=10&sort=frequency'

Response (200 OK):

{
  "status": "ok",
  "data": {
    "contacts": [
      {
        "id": "contact_001",
        "name": "Alice Chen",
        "email": "alice@example.com",
        "message_count": 42,
        "frequency": "high",
        "last_seen": "2026-01-15T09:30:00Z",
        "first_seen": "2025-01-01T08:00:00Z",
        "sentiment": "positive",
        "community_id": "team_a",
        "authority_score": 0.82,
        "hub_score": 0.45
      },
      {
        "id": "contact_002",
        "name": "Bob Martinez",
        "email": "bob@example.com",
        "message_count": 18,
        "frequency": "medium",
        "last_seen": "2026-02-20T14:15:00Z",
        "first_seen": "2025-03-10T10:30:00Z",
        "sentiment": "neutral",
        "community_id": "team_b",
        "authority_score": 0.51,
        "hub_score": 0.72
      }
    ],
    "pagination": {
      "total": 64,
      "limit": 10,
      "offset": 0,
      "pages": 7
    }
  },
  "timestamp": "2026-03-27T14:32:15Z"
}


3. Get Contact Details

GET /contacts/{contact_id}

Retrieve detailed information about a specific contact.

Path Parameters: - contact_id (string, required) — Contact ID

Request:

curl -X GET http://localhost:8000/contacts/contact_001

Response (200 OK):

{
  "status": "ok",
  "data": {
    "id": "contact_001",
    "name": "Alice Chen",
    "email": "alice@example.com",
    "message_count": 42,
    "frequency": "high",
    "last_seen": "2026-01-15T09:30:00Z",
    "first_seen": "2025-01-01T08:00:00Z",
    "sentiment": "positive",
    "community_id": "team_a",
    "authority_score": 0.82,
    "hub_score": 0.45,
    "message_ids": ["msg_001", "msg_004", "msg_012"],
    "common_topics": [
      {"topic_id": "project_planning", "frequency": 12},
      {"topic_id": "budget_review", "frequency": 8}
    ]
  },
  "timestamp": "2026-03-27T14:32:15Z"
}

Error Response (404 Not Found):

{
  "status": "error",
  "error": {
    "code": "NOT_FOUND",
    "message": "Contact contact_001 not found"
  },
  "timestamp": "2026-03-27T14:32:15Z"
}


4. List Messages

GET /messages

Retrieve messages from the archive.

Query Parameters: - limit (integer, optional, default=50) — Max results - offset (integer, optional, default=0) — Pagination offset - sort (string, optional, default=sent_at) — Sort by: sent_at, subject, from - from (string, optional) — Filter by sender email - thread_id (string, optional) — Filter by conversation thread - topic_id (string, optional) — Filter by topic

Request:

curl -X GET 'http://localhost:8000/messages?limit=20&sort=sent_at&topic_id=project_planning'

Response (200 OK):

{
  "status": "ok",
  "data": {
    "messages": [
      {
        "id": "msg_001",
        "thread_id": "thread_42",
        "from_email": "alice@example.com",
        "to_emails": ["bob@example.com", "charlie@example.com"],
        "subject": "Q1 Planning Discussion",
        "body": "Team, let's discuss the Q1 roadmap...",
        "body_tokens": 184,
        "sent_at": "2025-11-15T09:30:00Z",
        "received_at": "2025-11-15T09:31:00Z",
        "topic_id": "project_planning",
        "search_score": 0.89
      }
    ],
    "pagination": {
      "total": 247,
      "limit": 20,
      "offset": 0,
      "pages": 13
    }
  },
  "timestamp": "2026-03-27T14:32:15Z"
}


5. Get Message Details

GET /messages/{message_id}

Retrieve the full content of a specific message.

Path Parameters: - message_id (string, required) — Message ID

Request:

curl -X GET http://localhost:8000/messages/msg_001

Response (200 OK):

{
  "status": "ok",
  "data": {
    "id": "msg_001",
    "thread_id": "thread_42",
    "from_email": "alice@example.com",
    "to_emails": ["bob@example.com", "charlie@example.com"],
    "cc_emails": [],
    "bcc_emails": [],
    "subject": "Q1 Planning Discussion",
    "body": "Team,\n\nLet's discuss the Q1 roadmap and timeline. Key items:\n1. Budget allocation\n2. Resource planning\n3. Milestone definitions\n\nPlease review and comment by Friday.\n\nBest,\nAlice",
    "body_tokens": 184,
    "sent_at": "2025-11-15T09:30:00Z",
    "received_at": "2025-11-15T09:31:00Z",
    "topic_id": "project_planning",
    "thread_messages": ["msg_001", "msg_004", "msg_012"],
    "attachments": []
  },
  "timestamp": "2026-03-27T14:32:15Z"
}


6. Search Messages

POST /search

Full-text search across all messages using TF-IDF ranking.

Request Body:

interface SearchRequest {
    query: string;           // Search terms
    limit?: number;          // Max results (default: 20)
    filters?: {
        from?: string;       // Sender email filter
        topic_id?: string;   // Topic filter
        date_from?: string;  // ISO 8601 date
        date_to?: string;    // ISO 8601 date
    };
}

Request:

curl -X POST http://localhost:8000/search \
  -H 'Content-Type: application/json' \
  -d '{
    "query": "budget planning timeline",
    "limit": 10,
    "filters": {
      "topic_id": "project_planning",
      "date_from": "2025-11-01"
    }
  }'

Response (200 OK):

{
  "status": "ok",
  "data": {
    "query": "budget planning timeline",
    "results": [
      {
        "message_id": "msg_001",
        "rank": 1,
        "score": 0.94,
        "snippet": "...Q1 roadmap and timeline. Key items: Budget allocation, Resource planning...",
        "from_email": "alice@example.com",
        "subject": "Q1 Planning Discussion",
        "sent_at": "2025-11-15T09:30:00Z"
      },
      {
        "message_id": "msg_045",
        "rank": 2,
        "score": 0.87,
        "snippet": "...timeline for budget review is December 15th. Please prepare...",
        "from_email": "bob@example.com",
        "subject": "Budget Review Timeline",
        "sent_at": "2025-12-01T14:00:00Z"
      }
    ],
    "query_time_ms": 45
  },
  "timestamp": "2026-03-27T14:32:15Z"
}


7. List Topics

GET /topics

Retrieve all discovered topics/clusters from the archive.

Query Parameters: - limit (integer, optional, default=50) — Max results - sort (string, optional, default=frequency) — Sort by: frequency, name

Request:

curl -X GET 'http://localhost:8000/topics?limit=10&sort=frequency'

Response (200 OK):

{
  "status": "ok",
  "data": {
    "topics": [
      {
        "id": "project_planning",
        "name": "Project Planning",
        "description": "Q1 roadmap, timeline, milestones, deliverables",
        "message_count": 31,
        "top_keywords": ["planning", "timeline", "milestones", "deliverables", "roadmap"],
        "created_at": "2025-11-01T00:00:00Z"
      },
      {
        "id": "budget_review",
        "name": "Budget Review",
        "description": "Q1 budget allocation, resource planning, approvals",
        "message_count": 18,
        "top_keywords": ["budget", "allocation", "resources", "approval", "spending"],
        "created_at": "2025-11-01T00:00:00Z"
      }
    ],
    "total": 8
  },
  "timestamp": "2026-03-27T14:32:15Z"
}


8. Get Topic Details

GET /topics/{topic_id}

Retrieve detailed information about a specific topic.

Path Parameters: - topic_id (string, required) — Topic ID

Request:

curl -X GET http://localhost:8000/topics/project_planning

Response (200 OK):

{
  "status": "ok",
  "data": {
    "id": "project_planning",
    "name": "Project Planning",
    "description": "Q1 roadmap, timeline, milestones, deliverables",
    "message_count": 31,
    "top_keywords": ["planning", "timeline", "milestones", "deliverables", "roadmap"],
    "key_contacts": [
      {"contact_id": "contact_001", "name": "Alice Chen", "frequency": 12},
      {"contact_id": "contact_003", "name": "Diana Wu", "frequency": 8}
    ],
    "message_ids": ["msg_001", "msg_004", "msg_012"],
    "date_range": {
      "earliest": "2025-11-01T08:00:00Z",
      "latest": "2026-01-15T16:30:00Z"
    },
    "created_at": "2025-11-01T00:00:00Z"
  },
  "timestamp": "2026-03-27T14:32:15Z"
}


9. List Threads

GET /threads

Retrieve email conversation threads.

Query Parameters: - limit (integer, optional, default=50) — Max results - offset (integer, optional, default=0) — Pagination offset

Request:

curl -X GET 'http://localhost:8000/threads?limit=20'

Response (200 OK):

{
  "status": "ok",
  "data": {
    "threads": [
      {
        "id": "thread_42",
        "subject": "Q1 Planning Discussion",
        "message_count": 7,
        "participants": ["alice@example.com", "bob@example.com", "charlie@example.com"],
        "date_range": {
          "first_message": "2025-11-15T09:30:00Z",
          "last_message": "2025-11-20T14:00:00Z"
        },
        "topic_id": "project_planning"
      }
    ],
    "pagination": {
      "total": 42,
      "limit": 20,
      "offset": 0,
      "pages": 3
    }
  },
  "timestamp": "2026-03-27T14:32:15Z"
}


10. Get Thread Messages

GET /threads/{thread_id}/messages

Retrieve all messages in a conversation thread.

Path Parameters: - thread_id (string, required) — Thread ID

Request:

curl -X GET http://localhost:8000/threads/thread_42/messages

Response (200 OK):

{
  "status": "ok",
  "data": {
    "thread_id": "thread_42",
    "subject": "Q1 Planning Discussion",
    "messages": [
      {
        "id": "msg_001",
        "from_email": "alice@example.com",
        "to_emails": ["bob@example.com", "charlie@example.com"],
        "subject": "Q1 Planning Discussion",
        "body": "Team, let's discuss the Q1 roadmap...",
        "sent_at": "2025-11-15T09:30:00Z"
      },
      {
        "id": "msg_004",
        "from_email": "bob@example.com",
        "to_emails": ["alice@example.com"],
        "subject": "RE: Q1 Planning Discussion",
        "body": "Sounds good. I have concerns about resource allocation...",
        "sent_at": "2025-11-16T10:15:00Z"
      }
    ]
  },
  "timestamp": "2026-03-27T14:32:15Z"
}


11. Statistics

GET /stats

Retrieve high-level statistics about the extracted archive.

Request:

curl -X GET http://localhost:8000/stats

Response (200 OK):

{
  "status": "ok",
  "data": {
    "total_messages": 247,
    "total_contacts": 64,
    "total_topics": 8,
    "total_threads": 42,
    "pii_redactions": 512,
    "date_range": {
      "earliest": "2025-01-01T08:00:00Z",
      "latest": "2026-03-27T16:30:00Z"
    },
    "extraction_timestamp": "2026-03-27T14:32:18Z",
    "pipeline_version": "0.5.0"
  },
  "timestamp": "2026-03-27T14:32:15Z"
}


Error Codes

Code Status Description
OK 200 Success
INVALID_QUERY 400 Invalid request parameters
NOT_FOUND 404 Resource not found
INTERNAL_ERROR 500 Server error
UNIMPLEMENTED 501 Endpoint not yet implemented

Rate Limiting

No rate limiting in development. Production deployments should add:

// Cloudflare Workers KV-based rate limiter
const RATE_LIMIT = 100;  // requests per minute
const WINDOW_MS = 60000; // 1 minute

TypeScript Types

For client library integration:

interface Contact {
    id: string;
    name: string;
    email: string;
    message_count: number;
    frequency: 'high' | 'medium' | 'low';
    last_seen: string;    // ISO 8601
    first_seen: string;   // ISO 8601
    sentiment: 'positive' | 'neutral' | 'negative';
    community_id: string;
    authority_score: number;  // HITS algorithm
    hub_score: number;        // HITS algorithm
}

interface Message {
    id: string;
    thread_id: string;
    from_email: string;
    to_emails: string[];
    subject: string;
    body: string;
    body_tokens: number;
    sent_at: string;      // ISO 8601
    received_at: string;  // ISO 8601
    topic_id: string;
    search_score?: number;
}

interface Topic {
    id: string;
    name: string;
    description?: string;
    message_count: number;
    top_keywords: string[];
    created_at: string;   // ISO 8601
}

interface SearchResult {
    message_id: string;
    rank: number;
    score: number;
    snippet: string;
    from_email: string;
    subject: string;
    sent_at: string;
}

Example: Complete Workflow

# 1. Check API health
curl http://localhost:8000/health

# 2. Get statistics
curl http://localhost:8000/stats

# 3. Search for budget-related messages
curl -X POST http://localhost:8000/search \
  -H 'Content-Type: application/json' \
  -d '{"query": "budget allocation Q1"}'

# 4. Examine a specific topic
curl http://localhost:8000/topics/project_planning

# 5. Get key contacts in that topic
curl 'http://localhost:8000/contacts?limit=5&sort=frequency'

Next Steps


Version: 0.5.0 | Last Updated: Mar 27, 2026