AI · TribeMate
TribeMate is the institution AI tutor. Organisation servers call Partner AI with a partner token. Learners in Campus / widget call Ask with a verified user token. Both share one monthly prompt quota on the institution.
https://www.tribepeer.com/api. Partner routes need Authorization: Bearer <partner_jwt> and scope ai:chat.
Learner Ask needs a product JWT plus X-Institution-Uuid. Never put tp_sec_ in a browser.
Plans and quota
Quota counts successful completions on the institution for the current calendar month. Every AI response includes usage.
| API AI add-on | Unlocks Partner /ai/chat and Ask for API-built apps |
| Campus | Includes Ask for that school’s learners |
usage.quota | Monthly prompt allowance (0 = not entitled) |
usage.used | Successful prompts this month |
usage.remaining | quota − used, floored at 0 |
Organisation chat
/partner/v1/ai/chat
Run a tutor completion from your server. Prefer this for portals, LMS plugins, and backend-for-frontend apps.
Headers
Authorization | Bearer <access_token> from POST /partner/v1/auth/token |
Content-Type | application/json |
Accept | application/json |
Request body
Send either a single message (optional context), or a full messages array. If messages is present and non-empty, it wins.
message | string, max 8000 | Required when messages is omitted |
context | string, max 12000 | Optional system context (truncated server-side) |
messages | array, max 20 | Optional multi-turn transcript |
messages[].role | system | user | assistant | Required with messages |
messages[].content | string, max 8000 | Required with messages |
Example — single turn with lesson context
curl -s https://www.tribepeer.com/api/partner/v1/ai/chat \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"message": "Explain photosynthesis in two sentences.",
"context": "SS1 Biology · Module 2 · Leaf structure"
}'
const res = await fetch('https://www.tribepeer.com/api/partner/v1/ai/chat', {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
message: 'Explain photosynthesis in two sentences.',
context: 'SS1 Biology · Module 2 · Leaf structure',
}),
})
const data = await res.json()
console.log(data.reply, data.usage)
$data = Http::withToken($token)
->acceptJson()
->post('https://www.tribepeer.com/api/partner/v1/ai/chat', [
'message' => 'Explain photosynthesis in two sentences.',
'context' => 'SS1 Biology · Module 2 · Leaf structure',
])->json();
// $data['reply'], $data['model'], $data['usage']
import requests
r = requests.post(
'https://www.tribepeer.com/api/partner/v1/ai/chat',
headers={'Authorization': f'Bearer {token}'},
json={
'message': 'Explain photosynthesis in two sentences.',
'context': 'SS1 Biology · Module 2 · Leaf structure',
},
)
print(r.json()['reply'], r.json()['usage'])
Example — multi-turn messages
{
"messages": [
{ "role": "system", "content": "You are TribeMate for Lagos High School. Be brief." },
{ "role": "user", "content": "What is a cell?" },
{ "role": "assistant", "content": "A cell is the basic unit of life." },
{ "role": "user", "content": "Give one plant-cell organelle." }
]
}
Success response 200
{
"reply": "Photosynthesis converts light energy into chemical energy in plants…",
"model": "…",
"usage": { "quota": 2000, "used": 41, "remaining": 1959 }
}
Organisation usage
/partner/v1/ai/usage
Read the current month’s quota without spending a prompt.
curl -s https://www.tribepeer.com/api/partner/v1/ai/usage \ -H "Authorization: Bearer $TOKEN"
const res = await fetch('https://www.tribepeer.com/api/partner/v1/ai/usage', {
headers: { Authorization: `Bearer ${token}` },
})
console.log(await res.json())
$data = Http::withToken($token)->get('https://www.tribepeer.com/api/partner/v1/ai/usage')->json();
r = requests.get(
'https://www.tribepeer.com/api/partner/v1/ai/usage',
headers={'Authorization': f'Bearer {token}'},
)
print(r.json())
Success response 200
{
"usage": { "quota": 2000, "used": 41, "remaining": 1959 },
"enabled": true
}
enabled is false when the platform AI client is not configured.
Learner Ask (Campus / widget)
/product/v1/ai/ask
Verified human asks TribeMate. Counts against the same monthly quota.
Headers
Authorization | Bearer <product_jwt> — after email verification |
X-Institution-Uuid | Required |
Content-Type | application/json |
Request body
message | string, required, max 4000 | The learner’s question |
curl -s https://www.tribepeer.com/api/product/v1/ai/ask \
-H "Authorization: Bearer $USER_TOKEN" \
-H "X-Institution-Uuid: $INSTITUTION_UUID" \
-H "Content-Type: application/json" \
-d '{ "message": "What is osmosis?" }'
const res = await fetch('https://www.tribepeer.com/api/product/v1/ai/ask', {
method: 'POST',
headers: {
Authorization: `Bearer ${userToken}`,
'X-Institution-Uuid': institutionUuid,
'Content-Type': 'application/json',
},
body: JSON.stringify({ message: 'What is osmosis?' }),
})
const { reply, usage } = await res.json()
$data = Http::withToken($userToken)
->withHeaders(['X-Institution-Uuid' => $institutionUuid])
->post('https://www.tribepeer.com/api/product/v1/ai/ask', [
'message' => 'What is osmosis?',
])->json();
r = requests.post(
'https://www.tribepeer.com/api/product/v1/ai/ask',
headers={
'Authorization': f'Bearer {user_token}',
'X-Institution-Uuid': institution_uuid,
},
json={'message': 'What is osmosis?'},
)
print(r.json())
Success response 200
{
"reply": "Osmosis is the movement of water across a semi-permeable membrane…",
"usage": { "quota": 2000, "used": 42, "remaining": 1958 }
}
Errors
401 | Missing / invalid JWT |
403 | Missing ai:chat (Partner) or unverified user (product) |
402 | api_ai_required or ai_quota_exceeded (includes usage) |
422 | Validation |
429 | Rate limit |
ai_disabled | Platform model offline / not configured |
{
"error": "ai_quota_exceeded",
"message": "This institution has used its AI prompts for the month.",
"usage": { "quota": 2000, "used": 2000, "remaining": 0 }
}
Best practices
- Call Partner AI only from a server. Cache the partner token (~1 hour).
- Pass lesson text in
contextor a system message — never put secrets in prompts. - Poll
GET /ai/usagebefore batch jobs; stop whenremainingis low. - For Campus UIs, use Ask + user JWT. Do not mint partner tokens in the webview.
- Surface
usage.remainingto staff so schools know when the month’s prompts are gone.