AIPAKA AIPAKA
Developers

AIPAKA API

Ask questions of the Pistoia Alliance knowledge base from your own systems. AIPAKA answers using Pistoia Alliance webinars, meetings, documents and website content, and returns the sources it used.

Requesting access

API access is not self-service. To use the API, contact your Pistoia Alliance representative or the Alliance team and tell them what you want to build. If approved, the Alliance creates a named access token for your system and sends it to you securely.

Tokens must never be shared with another organisation

A token is issued to one organisation, for its own use only. It must not be shared with, passed to, or used on behalf of any other organisation, for any reason. If sharing is identified, the token will be revoked without notice. If another organisation needs access, it must request its own token from the Alliance.

Overview

Base URL: https://insight.pistoiaalliance.org

Each client system gets its own token. A token is tied to your system's name and:

Check that the service is running (no token needed):

curl https://insight.pistoiaalliance.org/health

Authentication

Send your token in either header:

Authorization: Bearer pa_s2s_your-system_xxxxxxxxxxxxxxxxxxxx
X-API-Key: pa_s2s_your-system_xxxxxxxxxxxxxxxxxxxx

Tokens in the URL are not accepted. Any authentication failure returns 401 with {"detail": "Authentication required."}, whatever the cause (missing, wrong, expired or revoked).

Do not share your token with any other organisation

Your token belongs to your organisation alone. Sharing it with any other organisation, for any reason, breaches the terms of access and will result in the token being revoked.

Treat the token like a password. Keep it in a secrets manager or environment variable. Call the API from your server, never from a web page or mobile app, which would expose it. A token cannot be viewed again after it is issued; if it is lost or leaked, ask the Alliance to revoke it and issue a new one.

POST/chat

Ask a question and receive an answer with the sources it was drawn from. Send JSON with Content-Type: application/json.

Request

FieldTypeDescription
querystring, requiredYour question, 1–2000 characters.
session_idstring or nullOmit or null to start a new conversation. Pass the value from a previous response to ask a follow-up.
top_kintegerNumber of source excerpts to retrieve, 1–20 (default 8).
filtersobjectOptional. speakers (list of names), date_from and date_to (ISO dates such as 2025-01-01), session (partial session name).

Response

{
  "answer": "The Pistoia Alliance's FAIR maturity work ...",
  "sources": [
    {
      "session_name": "FAIR Maturity Matrix Introduction",
      "session_date": "2025-03-04",
      "speaker": "Jane Smith",
      "timestamp": "00:12:40",
      "text": "...the excerpt used to support the answer...",
      "score": 0.0312,
      "source_kind": "transcript",
      "content_label": "Video",
      "citation_url": "https://pistoiaalliance.org/resource-library/...",
      "direct_citation_url": "https://vimeo.com/1008786712#t=760"
    }
  ],
  "query": "What has the Pistoia Alliance said about FAIR data maturity?",
  "session_id": "5b1f2c0e-8a4e-4a52-9c1f-0e7a6a1d2b33"
}
FieldDescription
answerThe generated answer, with light Markdown and inline citations such as [Session: … | Date: 2025-03-04 | Speaker: … | ~00:12:40] or [Document: … | Date: …].
sourcesThe excerpts the answer was based on. May be empty: questions about counts or lists of events are answered from a structured catalogue and carry no excerpts.
session_idAlways returned. Pass it back to continue the conversation.
sources[].content_labelDisplay label such as Video, Transcript, Document, Write-up, Page, Project, Event or FAQ.
sources[].citation_url, direct_citation_urlLinks to the item and to the underlying resource. Either may be null. Addresses starting with https:// are ordinary links (members-only pages still ask the reader to sign in). Addresses starting with / belong to the AIPAKA web app and only open for signed-in members.
About the content. Answers draw on the full Pistoia Alliance library, including members-only material, exactly as for a signed-in member. Make sure your own users are entitled to see that content, and do not republish excerpts beyond what your agreement with the Alliance allows. Answers are produced by an AI model and can be wrong or incomplete, so keep the citations visible so people can check.

Conversations

Errors and limits

StatusMeaningWhat to do
200Success
401Missing, invalid, expired or revoked token, or an endpoint other than POST /chatCheck the header and the token's expiry; contact the Alliance.
422Invalid request body (empty or over-long query, top_k out of range)Fix the request; do not retry unchanged.
429Per-minute limit exceeded; includes Retry-After: 60Wait, then retry. Space requests out or ask for a higher limit.
429{"detail": "Monthly allowance exceeded."} — you have used your agreed number of calls for this calendar month. Retry-After is the number of seconds until the allowance resets.Do not retry before then: the allowance resets on the 1st of each month (UTC). Contact the Alliance if you need more.
5xxTemporary problemRetry with backoff (2s, 4s, 8s), up to 3 times.

Answers usually take a few seconds and can take longer for complex questions, so set your client timeout to at least 60 seconds. Each call uses a paid AI model: cache answers to repeated questions where sensible and avoid automated loops.

Examples

curl

curl -X POST https://insight.pistoiaalliance.org/chat \
  -H "Authorization: Bearer $AIPAKA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query": "Which sessions covered the IDMP ontology?"}'

Python

import os, requests

BASE = "https://insight.pistoiaalliance.org"
HEADERS = {"Authorization": f"Bearer {os.environ['AIPAKA_TOKEN']}"}

def ask(query, session_id=None):
    r = requests.post(f"{BASE}/chat", headers=HEADERS,
                      json={"query": query, "session_id": session_id}, timeout=90)
    r.raise_for_status()
    return r.json()

first = ask("Which sessions covered the IDMP ontology?")
print(first["answer"])
follow_up = ask("Which of those were in 2024?", session_id=first["session_id"])
print(follow_up["answer"])

JavaScript (Node, server side)

const res = await fetch("https://insight.pistoiaalliance.org/chat", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.AIPAKA_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ query: "What were the main points on knowledge graphs?",
                         filters: { date_from: "2025-01-01", date_to: "2025-12-31" } }),
  signal: AbortSignal.timeout(90_000),
});
if (!res.ok) throw new Error(`AIPAKA error ${res.status}`);
const { answer, sources, session_id } = await res.json();

Before you go live

For a new token, a higher rate limit, or to replace or revoke a token, contact the Alliance and quote your system name (the part of the token after pa_s2s_). Never send the token itself by email or chat.