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_KEYGet 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
| Field | Description |
|---|---|
answer | The agent's analysis in markdown. |
threadId | Conversation thread ID. Pass back to continue the conversation. |
reasoning | The model's internal reasoning (or null). |
thinking.tools | Human-readable labels of analytics tools called. |
thinking.events | Event names queried from your data. |
thinking.segments | User segments compared. |
thinking.dateRange | Date range filter applied (if any). |
thinking.toolCalls | Ordered 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).
| Param | Description |
|---|---|
tags | Comma-separated tag filter |
q | Search query |
limit | Max 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.
| Param | Description |
|---|---|
is_active | true 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
}'| Field | Description |
|---|---|
insight_id | Required. ID of a recipe insight to execute on schedule. |
name | Required. Human-readable label. |
cadence | Required. daily, weekly, or monthly. |
repeat_count | Optional. 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
| Endpoint | Limit |
|---|---|
POST /api/agent/ask | 60 requests/minute |
| All other endpoints | 120 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
| Status | Meaning |
|---|---|
| 400 | Bad request — missing or invalid parameters |
| 401 | Unauthorized — invalid or missing API key |
| 403 | Forbidden — thread does not belong to your company |
| 429 | Rate limit exceeded |
| 500 | Internal server error |
Set up as a Claude Code skill
Create this file in your project to add a /analytics skill:
.claude/skills/analytics/SKILL.mdContents:
---
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_KEYThen 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.mdUse 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