API Reference

Product Analyst AI — Public API

Authentication

All API requests require a company API key passed as a Bearer token:

Authorization: Bearer pai_YOUR_API_KEY

Get your API key from Settings > API in the dashboard.

Ask a question

POST /api/agent/ask

Ask the AI product analyst a question about your data. Returns a structured JSON response with the answer, thinking metadata, and tool call details.

Request

curl -X POST https://productanalyst.ai/api/agent/ask \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer pai_YOUR_API_KEY" \
  -d '{
    "question": "What events predict conversion?",
    "threadId": "optional — pass to continue a conversation"
  }'

Response

{
  "answer": "**Key finding:** ...",
  "threadId": "apikey:company123:a1b2c3d4",
  "reasoning": "Checked event adoption rates across all users...",
  "thinking": {
    "dataSource": "PostHog",
    "tools": ["Checking event adoption rates", "Comparing adoption between groups"],
    "events": ["signup_complete", "upgrade_clicked"],
    "segments": ["pro_users", "free_users"],
    "dateRange": { "from": "2026-01-01", "to": "2026-02-01" },
    "toolCalls": [
      {
        "tool": "event_penetration",
        "label": "Checking event adoption rates",
        "args": { "event": "signup_complete" }
      }
    ],
    "reasoning": "Checked event adoption rates across all users..."
  }
}

Response fields

FieldDescription
answerThe agent's analysis in markdown.
threadIdConversation thread ID. Pass back to continue the conversation.
reasoningThe model's internal reasoning (or null).
thinking.toolsHuman-readable labels of analytics tools called.
thinking.eventsEvent names queried from your data.
thinking.segmentsUser segments compared.
thinking.dateRangeDate range filter applied (if any).
thinking.toolCallsOrdered list of every tool invocation with full arguments.

Threads

List threads

GET /api/agent/threads

List all conversation threads for your company.

curl https://productanalyst.ai/api/agent/threads \
  -H "Authorization: Bearer pai_YOUR_API_KEY"

Get thread messages

GET /api/agent/threads/:threadId/messages

Retrieve full message history. URL-encode the threadId (colons become %3A).

curl https://productanalyst.ai/api/agent/threads/apikey%3Acompany123%3Aa1b2c3d4/messages \
  -H "Authorization: Bearer pai_YOUR_API_KEY"

Insights

List insights

GET /api/insights

Retrieve saved insights (team knowledge base).

ParamDescription
tagsComma-separated tag filter
qSearch query
limitMax results

Create insight

POST /api/insights

Save a new insight. The agent auto-retrieves relevant insights when answering questions.

curl -X POST https://productanalyst.ai/api/insights \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer pai_YOUR_API_KEY" \
  -d '{
    "content": "Users who invite a team member within 7 days convert at 3.2x the rate.",
    "title": "Team invite drives conversion",
    "tags": ["conversion", "activation"],
    "source": "api"
  }'

Agents

Set up recurring reports on saved recipes. Agents execute a recipe insight on a schedule and notify your team.

List agents

GET /api/agents

Retrieve all agents for your company. Filter by active status.

ParamDescription
is_activetrue or false
curl https://productanalyst.ai/api/agents?is_active=true \
  -H "Authorization: Bearer pai_YOUR_API_KEY"

Create agent

POST /api/agents

Set up a recurring agent on a saved recipe. The referenced insight must have the recipe tag.

curl -X POST https://productanalyst.ai/api/agents \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer pai_YOUR_API_KEY" \
  -d '{
    "insight_id": "uuid of a recipe insight",
    "name": "Weekly onboarding report",
    "cadence": "weekly",
    "repeat_count": null
  }'
FieldDescription
insight_idRequired. ID of a recipe insight to execute on schedule.
nameRequired. Human-readable label.
cadenceRequired. daily, weekly, or monthly.
repeat_countOptional. null for infinite, or a positive integer for N runs before auto-deactivating.

Update agent

PUT /api/agents/:id

Partially update an agent. Changing cadence recomputes the next run time.

curl -X PUT https://productanalyst.ai/api/agents/AGENT_ID \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer pai_YOUR_API_KEY" \
  -d '{
    "cadence": "daily",
    "is_active": false
  }'

Delete agent

DELETE /api/agents/:id

Permanently delete an agent.

curl -X DELETE https://productanalyst.ai/api/agents/AGENT_ID \
  -H "Authorization: Bearer pai_YOUR_API_KEY"

Rate Limits

EndpointLimit
POST /api/agent/ask60 requests/minute
All other endpoints120 requests/minute

Rate limit headers are included on every response: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.

When rate limited, you receive HTTP 429 with a Retry-After header (seconds).

Error Codes

StatusMeaning
400Bad request — missing or invalid parameters
401Unauthorized — invalid or missing API key
403Forbidden — thread does not belong to your company
429Rate limit exceeded
500Internal server error

Set up as a Claude Code skill

Create this file in your project to add a /analytics skill:

.claude/skills/analytics/SKILL.md

Contents:

---
name: analytics
description: Query product analytics. Use when the user asks about metrics, funnels, retention, conversion, or user behavior.
argument-hint: "your question about the data"
allowed-tools: Bash(curl *)
---

Query product analytics for: $ARGUMENTS

Run:
curl -s -X POST https://productanalyst.ai/api/agent/ask \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer $PAI_API_KEY" \
  -d "{\"question\": \"$ARGUMENTS\"}"

## Interpreting the response

- answer: the analysis in markdown with data-backed findings
- reasoning: the model's internal reasoning (or null)
- thinking.tools: which analytics tools ran (e.g. "Checking event adoption rates")
- thinking.events: event names queried from the data
- thinking.segments: user segments that were compared
- thinking.dateRange: date range filter applied
- thinking.toolCalls: full list of tool invocations with arguments
- threadId: pass back in follow-up questions to continue the conversation

For follow-ups, include the threadId:
curl -s -X POST https://productanalyst.ai/api/agent/ask \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer $PAI_API_KEY" \
  -d "{\"question\": \"YOUR_FOLLOWUP\", \"threadId\": \"THREAD_ID\"}"

Use thinking.events and thinking.segments to understand what was
analyzed and formulate better follow-up questions.

Commit this file to your repo — anyone who clones it gets the skill automatically.

Set your API key as an environment variable:

export PAI_API_KEY=pai_YOUR_API_KEY

Then invoke it with: /analytics What events predict conversion?

Set up as an Open Code skill

Create this file in your project:

.opencode/skills/analytics/SKILL.md

Use the same contents as the Claude Code skill above. Open Code discovers skills from the .opencode/skills/ directory the same way.

Alternative: add to CLAUDE.md

If you prefer not to use a skill, paste this into your project's CLAUDE.md:

## Product Analytics

Query product analytics via the Product Analyst AI API.
Base URL: https://productanalyst.ai

To ask a question:
curl -s -X POST https://productanalyst.ai/api/agent/ask \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer $PAI_API_KEY" \
  -d '{"question": "YOUR_QUESTION"}'

Response fields:
- answer: markdown analysis
- reasoning: model's internal reasoning (or null)
- thinking: metadata (tools, events, segments, dateRange, toolCalls)
- threadId: pass back to continue the conversation
API Documentation - Product Analyst AI