API reference
Organisation API
Partner JWT API for servers you control. Create classes, curriculum, join codes, grade work, manage communities, and call TribeMate.
Base path: https://www.tribepeer.com/api/partner/v1.
Exchange
tp_id_ +
tp_sec_ for a Bearer token. Live keys return
402 until Live / Widget Pro / Campus is granted.
Scopes on the token gate each route. Full AI docs:
AI · TribeMate .
Authentication
POST
/partner/v1/auth/token
Public. Returns a partner JWT (~1 hour). Call only from a server.
Request body
client_idstring, required tp_id_…
client_secretstring, required tp_sec_… — never ship to browsers
POST /api/partner/v1/auth/token
cURL
JavaScript
PHP
Python
Copy
curl -s https://www.tribepeer.com/api/partner/v1/auth/token \
-H "Content-Type: application/json" \
-d '{
"client_id": "tp_id_…",
"client_secret": "tp_sec_…"
}'
const res = await fetch('https://www.tribepeer.com/api/partner/v1/auth/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
client_id: process.env.TP_CLIENT_ID,
client_secret: process.env.TP_CLIENT_SECRET,
}),
})
const { access_token, expires_in, scopes } = await res.json()
$response = Http::acceptJson()->post('https://www.tribepeer.com/api/partner/v1/auth/token', [
'client_id' => env('TP_CLIENT_ID'),
'client_secret' => env('TP_CLIENT_SECRET'),
]);
$token = $response->json('access_token');
import os, requests
r = requests.post('https://www.tribepeer.com/api/partner/v1/auth/token', json={
'client_id': os.environ['TP_CLIENT_ID'],
'client_secret': os.environ['TP_CLIENT_SECRET'],
})
token = r.json()['access_token']
Success 200
application/json Copy
{
"access_token": "eyJ…",
"token_type": "Bearer",
"expires_in": 3600,
"expires_at": "2026-09-06T12:00:00+00:00",
"scopes": ["tribes:read", "tribes:write", "ai:chat", "…"]
}
Errors
401Invalid client credentials
403Key deactivated or institution inactive
402Live key without a paying plan
Institution profile & branding
Who this key belongs to, branding, key state, and scopes.
Header: Authorization: Bearer <token>
Response 200
application/json Copy
{
"institution": {
"uuid": "…",
"name": "Lagos High School",
"organization_type": "school",
"status": "active",
"owner": { "name": "…", "email": "…", "username": "…" }
},
"branding": {
"display_name": "Lagos High",
"logo_url": "https://…",
"accent_hex": "#9A3412",
"welcome_markdown": "…"
},
"api_key": {
"id": 12,
"name": "Production",
"client_id": "tp_id_…",
"is_active": true,
"state": "live"
},
"scopes": ["tribes:read", "tribes:write", "…"]
}
PATCH
/partner/v1/me/branding
Update Campus / widget brand. Partial updates allowed.
Request body
display_namestring ≤160 optional
logo_urlstring ≤500 optional (pass null to clear)
accent_hex#RGB / #RRGGBBoptional; # added if missing
welcome_markdownstring ≤8000 optional
Response 200
application/json
{ "branding": { "display_name": "Lagos High", "logo_url": null, "accent_hex": "#9A3412", "welcome_markdown": null } }
Tribes (classes)
GET /tribestribes:readList classes for this institution
POST /tribestribes:writeCreate a class
GET /tribes/{uuid}tribes:readShow one class
PATCH /tribes/{uuid}tribes:writeUpdate metadata
POST /tribes/{uuid}/publishtribes:writePublish
POST /tribes/{uuid}/archivetribes:writeArchive
DEL /tribes/{uuid}tribes:writeDelete
Scope: tribes:write
Create a class owned by the institution owner.
Request body
titlestring ≤120, required
categoryrequired · TribeCategory value (e.g. science, technology)
aboutstring ≤2000, optional
tagsarray|string, optional
visibilitypublic | private_listed | hidden (default hidden)
access_typefree | paid | tpt
price_kobointeger ≥0 when paid
tpt_costinteger ≥0 when tpt
publishboolean — publish immediately
POST /api/partner/v1/tribes
cURL
JavaScript
PHP
Python
Copy
curl -s https://www.tribepeer.com/api/partner/v1/tribes \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "SS1 Biology",
"category": "science",
"about": "Term 1 cohort",
"visibility": "hidden",
"access_type": "free",
"publish": true
}'
await fetch('https://www.tribepeer.com/api/partner/v1/tribes', {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
title: 'SS1 Biology',
category: 'science',
about: 'Term 1 cohort',
visibility: 'hidden',
access_type: 'free',
publish: true,
}),
}).then(r => r.json())
$tribe = Http::withToken($token)->post('https://www.tribepeer.com/api/partner/v1/tribes', [
'title' => 'SS1 Biology',
'category' => 'science',
'about' => 'Term 1 cohort',
'visibility' => 'hidden',
'access_type' => 'free',
'publish' => true,
])->json();
r = requests.post('https://www.tribepeer.com/api/partner/v1/tribes',
headers={'Authorization': f'Bearer {token}'},
json={
'title': 'SS1 Biology',
'category': 'science',
'visibility': 'hidden',
'access_type': 'free',
'publish': True,
})
print(r.json())
Tribe members
GET /tribes/{uuid}/membersmembers:read
POST /tribes/{uuid}/membersmembers:write · body: user lookup fields
PATCH /tribes/{uuid}/membersmembers:write · role / active
DEL /tribes/{uuid}/membersmembers:write
GET /tribes/{uuid}/invitationsmembers:read
Announcements
GET /tribes/{uuid}/announcementsannouncements:read
POST /tribes/{uuid}/announcementsannouncements:write
GET /tribes/{uuid}/announcements/{announcementUuid}
PATCH / DEL update / delete announcement
POST …/publish · …/pinpublish or pin
Modules & materials
GET /tribes/{uuid}/modulesmaterials:read
POST /tribes/{uuid}/modulesbody: title, optional description
PATCH / DEL /modules/{moduleUuid}materials:write
GET /tribes/{uuid}/materialsquery: type, module_uuid
POST /tribes/{uuid}/materialscreate text / quiz / assignment
GET / PATCH / DEL /materials/{materialUuid}
POST …/materials/{materialUuid}/publishpublish lesson
POST
/partner/v1/tribes/{uuid}/materials
Scope: materials:write
Create a lesson, quiz, or assignment under a module.
Common fields
module_uuiduuid, required (or module_id)
typetext | quiz | assignment
titlestring ≤255, required
descriptionoptional
contentlesson body (text) or unused when quiz uses questions
is_publishedboolean
requires_prevboolean — gate behind previous material
pass_score1–100 (quiz)
max_attemptsinteger ≥1 (quiz)
timing_mode / time_limit_secondsquiz timing
questionsarray of quiz questions (serialized into content)
deadline_atrequired for new assignments
submission_modefile | text | both (assignments)
instructionsassignment brief
Example quiz body
JSON Copy
{
"module_uuid": "…",
"type": "quiz",
"title": "Leaf structure check",
"pass_score": 70,
"max_attempts": 2,
"is_published": true,
"questions": [
{
"prompt": "Where does photosynthesis mainly occur?",
"type": "mcq",
"options": ["Root", "Leaf", "Stem"],
"answer": "Leaf"
}
]
}
Response 201
{ "material": { "uuid", "module_uuid", "type", "title", "is_published", "questions"| "content", … } }
Submissions & grading
GET /tribes/{uuid}/submissionssubmissions:read · quiz + assignment rows
POST /tribes/{uuid}/submissions/assignments/{submissionUuid}/gradesubmissions:write
Grade body typically includes score / feedback fields accepted by the grading controller. Prefer the Learner manage routes if staff work inside Campus UI.
Join codes & enrollments
GET /join-codesjoin_codes:write
POST /join-codesbody: tribe_uuid, optional label, max_uses, expires_at
POST /join-codes/{code}/revokerevoke
POST /enrollmentsenrollments:write · place a learner by email / user id into a tribe
Students & results
GET /studentsstudents:read · query filters as validated by controller
GET /resultsresults:read · scores across your tribes
Communities & chat
Institution-owned communities, members, join requests, threads, and messages.
GET / POST /communitieslist / create
GET / PATCH / DEL /communities/{uuid}CRUD
/communities/{uuid}/membersGET/POST/PATCH/DELETE · scopes communities:read / community_members:write
/invitations, /join-requests, approve/rejectmembership workflow
/threads, /threads/{threadUuid}/messagesclassroom chat · community_messages:write to post
pin / lock / read / message PATCH|DELETE moderation
AI
POST /ai/chat and GET /ai/usage (scope ai:chat).
Full request / response / multi-language samples: AI · TribeMate reference .
Common errors
401Missing or expired partner JWT
403Scope missing on token
402Plan / AI entitlement / quota
404Tribe / material not in this institution
422Validation
429Throttle
Learner API →
AI docs