Researcher API
Run AI-scored personality assessments over HTTP and retrieve the scored results.
Authentication
Every request authenticates with an API key sent as a bearer token:
Authorization: Bearer <your-api-key>Create keys in Settings → Researcher API Keys. Keys are tied to your account and carry its subscription tier:
- Catalog endpoints (
GET /inventory*) work with any valid key, on any tier. - Assessment creation, result export, and all batch endpoints require a Researcher subscription. A valid key on a lower tier gets
403 Forbidden.
AI runs are metered: by default they draw on your account's credit balance, or use your own stored provider key when you have one connected. A run that can't be paid for returns 402 with an explanation and an upgrade/connect URL.
Quickstart
From zero to a scored assessment in three calls:
# 1. Find an inventory (id is what you pass as inventoryId)
curl -s https://ipsyc.io/api/v1/inventory \
-H "Authorization: Bearer $IPSYC_API_KEY"
# 2. Run an assessment: an AI model answers the inventory, we score it
curl -s -X POST https://ipsyc.io/api/v1/assessment \
-H "Authorization: Bearer $IPSYC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Rate yourself on a 1-5 Likert scale for each of the following statements.",
"model": "qwen/qwen3.7-flash",
"inventoryId": "bfi10"
}'
# 3. Fetch the stored result later by its id
curl -s https://ipsyc.io/api/v1/assessment/<id> \
-H "Authorization: Bearer $IPSYC_API_KEY"A successful run returns 201 Created with the session id, the scored scales (and subscales, where the inventory defines them), and any scoring warnings.
POST /api/v1/assessment
The request body has four fields:
{
"prompt": string, // required, 1–5000 chars — instruction for the model
"model": string, // required, 1–200 chars — e.g. "qwen/qwen3.7-flash"
"inventoryId": string, // required, 1–100 chars — an id from GET /inventory
"provider": "openai" | "huggingface" | "openrouter" // optional; derived from the model when omitted
}Your prompt is sent to the model together with the inventory's item list, so a short instruction like the default above is enough — you do not need to enumerate items yourself. The model's answers are scored server-side against the inventory's scoring key.
Responses
201 Created
{
"data": {
"id": "…", // session id — use with GET /assessment/{id}
"inventoryId": "bfi10",
"type": "ai",
"aiModel": "gpt-4o-mini",
"timestamp": "…",
"results": { "scales": { … }, "subscales": { … } },
"warnings": []
}
}Errors
400 Invalid JSON body or schema violation (error = per-field messages)
Unknown inventoryId: the body names the code, lists the
supported inventories, and points at GET /inventory
401 Missing/invalid API key (WWW-Authenticate: Bearer)
402 Run can't be paid for: no stored provider key, no credits, or
tier denies the run (error explains; includes upgradeUrl where apt)
403 Key valid but account is not on the Researcher tier
422 Model response failed validation (e.g. items missing from the answer)
429 Rate limit exceeded (20 assessments/min per key)Endpoints
GET /api/v1/health any tier
GET /api/v1/inventory any tier ?offset&limit&search
GET /api/v1/inventory/{id} any tier
GET /api/v1/inventory/{id}/items any tier ?offset&limit
GET /api/v1/inventory/{id}/scales any tier ?offset&limit
GET /api/v1/assessment any tier ?offset&limit (your runs)
POST /api/v1/assessment researcher
GET /api/v1/assessment/{id} any tier
GET /api/v1/assessment/{id}/export/{format} researcher format: csv|json
GET /api/v1/batch researcher ?offset&limit
POST /api/v1/batch researcher (≤10 models, ≤5 inventories)
GET /api/v1/batch/{id} researcher (batch status + items)PDF export is not yet available via the API (use the web interface); csv and json are. List endpoints return { data: [...], total, offset, limit }; single resources return { data: {...} }; errors return { error: "…" }. Pagination defaults: offset=0, limit=25 (max 100).
OpenAPI spec
The complete machine-readable spec (OpenAPI 3.0) is served at /api/v1/openapi — load it into Swagger UI, Insomnia, or any OpenAPI client to generate a client for your language.