Skip to Content
Go API referenceAgent & UI integration recipes

Agent & UI integration recipes

These are live-source-audited examples for application code and agents. The audit target is GitHub master commit b504e4d, which matches the active local Go source used to prepare these requests. Each payload contains only keys decoded by the active handler; placeholder IDs and tokens are intentionally non-production values.

One-time client configuration

export GO_API="https://api.example.com/api/v1" export AGENT_GATEWAY="https://agent.example.com" export ACCESS_TOKEN="<Kibegi user access JWT>" export GATEWAY_TOKEN="<optional agent gateway service token>" export INDEXER="http://indexer.internal:8090" export INDEXER_TOKEN="<private indexer service token>" export CLASS_ID="11111111-2222-3333-4444-555555555555" export UPLOAD_ID="66666666-7777-8888-9999-aaaaaaaaaaaa"

All direct Go writes use Content-Type: application/json, except multipart upload/image operations. A successful mutation normally returns the Go envelope. Store the access value from login under an encrypted user session; do not expose refresh tokens, service tokens, or provider keys to browser code.

Identity creation and session acquisition

Register a student

Source: RegisterHandler

curl --fail-with-body -X POST "$GO_API/auth/register/" \ -H 'Content-Type: application/json' \ --data '{ "email":"asha.mrema@example.com", "full_name":"Asha Mrema", "user_type":"student", "password":"SecurePass9", "confirm_password":"SecurePass9" }'
{ "success": true, "message": "Registration initiated. Check your email for the verification code.", "data": null, "errors": null }

The active handler returns 400 for a duplicate email, a blank/invalid field, a mismatched confirmation, an unsupported user type, or a password shorter than eight characters/all-numeric. It can return 503 when the registration or mail dependency is unavailable.

Verify the registration OTP and receive tokens

Source: RegisterVerifyHandler

curl --fail-with-body -X POST "$GO_API/auth/register/verify/" \ -H 'Content-Type: application/json' \ --data '{ "email":"asha.mrema@example.com", "otp":"123456", "university":"Kibegi University", "phone_number":"+255712345678" }'

For an approved student, data contains the user profile and tokens.access/tokens.refresh. A lecturer may instead receive 200 with a pending-approval message and no token pair. Invalid or expired OTPs return 400; missing pending user returns 404.

Log in and refresh

curl --fail-with-body -X POST "$GO_API/auth/login/" \ -H 'Content-Type: application/json' \ --data '{"email":"asha.mrema@example.com","password":"SecurePass9"}' curl --fail-with-body -X POST "$GO_API/auth/token/refresh/" \ -H 'Content-Type: application/json' \ --data '{"refresh":"<refresh JWT>"}'

The login response is the normal envelope with data.user and data.tokens. Refresh is deliberately a direct JSON object, { "access": "…", "refresh": "…" }; failed refreshes use direct { "detail": "Token is invalid or expired" } with 401.

Classes and member onboarding

Insert a class

Source: CreateHandler

curl --fail-with-body -X POST "$GO_API/classes/" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H 'Content-Type: application/json' \ --data '{ "name":"Distributed Systems", "description":"Term 1 learning space", "is_public":false }'

The returned data includes the generated UUID, class_code, creator, member_count, the join_qr_payload, and join_qr_value. The server rejects a missing/blank name with 400; an invalid/missing user token is 401.

Join a class from a code or QR payload

curl --fail-with-body -X POST "$GO_API/classes/join/" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H 'Content-Type: application/json' \ --data '{"class_code":"ABCD12"}'

The QR payload’s class_code is the value to submit. Invalid or already-joined codes return 400; a successful join returns the class detail envelope.

Files, storage, and AI ingestion

Insert an upload

Source: uploads.create

curl --fail-with-body -X POST "$GO_API/uploads/" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -F "class_obj=$CLASS_ID" \ -F 'file=@./week-01-notes.pdf;type=application/pdf' \ -F 'file_name=week-01-notes.pdf'

The file and UUID class_obj form parts are required; file_name is optional. The Go handler enforces a 50 MiB limit, returns 400 for malformed multipart, missing files, invalid class UUID, or too-large files; 403 for no class upload permission; 502 for object-store failure; and 503 when storage or the upload service is unavailable.

The success envelope’s data includes id, file_name, file_type, file_size, file_code, file, file_url, uploader, class_obj, is_deleted, deleted_at, and timestamps. Once the database record is committed, Go calls the private indexer with { "force": false }.

Read index status through the Go API

curl --fail-with-body "$GO_API/ai/status/$UPLOAD_ID/" \ -H "Authorization: Bearer $ACCESS_TOKEN"

This is the browser and UI-safe status path. It returns the persisted processing job when one exists or the exact fallback object { "status":"not_started", "chunks_created":0 }. Do not send the indexer’s private token to a UI.

Share and collaboration insertions

Share one upload

Source: sharing.create

curl --fail-with-body -X POST "$GO_API/sharing/" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H 'Content-Type: application/json' \ --data '{ "file_code":"ABC123", "shared_with_id":42, "message":"Please review these notes." }'

201 returns the share detail. A file that is missing/deleted, already shared to that user, or not owned/authorized returns 400; service failure is 503. Use POST /sharing/{share_uuid}/accept/ with no body to transition a recipient share, then GET /sharing/{share_uuid}/download/ for the bytes.

Send a friend request

curl --fail-with-body -X POST "$GO_API/friends/add/" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H 'Content-Type: application/json' \ --data '{"email":"friend@example.com"}'

The handler accepts either a user_id or an email. It returns 400 if neither resolves to a valid request input. Request-state changes use POST /friends/{friendship_id}/accept/, /decline/, or /cancel/ without a JSON body; nickname update uses PATCH /friends/{friendship_id}/nickname/ with { "nickname":"Study partner" }.

Schedules, public registration, and assignments

Create a calendar and event

Source: schedule handlers

curl --fail-with-body -X POST "$GO_API/schedule/calendars/" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H 'Content-Type: application/json' \ --data '{"name":"Term calendar","description":"Teaching plan","is_public_sync":false}' curl --fail-with-body -X POST "$GO_API/schedule/calendars/$CLASS_ID/events/" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H 'Content-Type: application/json' \ --data '{ "title":"Distributed systems lecture", "description":"Consensus introduction", "location":"Room A", "start_at":"2026-09-01T08:00:00Z", "end_at":"2026-09-01T10:00:00Z", "event_type":"class", "recurrence":"weekly", "days":["monday"], "reminder_minutes":30 }'

Use the calendar UUID returned by the first call for the event URL; do not use the class UUID shown in the shell placeholder for a real client. Event title, start_at, and end_at are required. Invalid timestamps, unavailable calendar access, and invalid recurrence settings produce handler validation/authorization errors.

Public class communications contact registration

curl --fail-with-body -X POST "$GO_API/public/class-comms/<public-token>/register/" \ -H 'Content-Type: application/json' \ --data '{ "full_name":"Asha Mrema", "phone_number":"+255712345678", "consent_granted":true, "notes":"Parent contact" }'

The public route requires no user JWT but is available only for a token whose class profile enables public registration. full_name and phone_number are the validated data fields; the contact is upserted by class and phone. Failed registration/access returns the normal error envelope.

Create a class assignment and submit a response

curl --fail-with-body -X POST "$GO_API/assignments/classes/$CLASS_ID/" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H 'Content-Type: application/json' \ --data '{ "title":"Network report", "description":"Research a protocol", "instructions":"Submit a concise report", "attachment":"uploads/42/brief.pdf", "due_date":"2026-09-10T16:00:00Z", "max_score":100, "is_active":true, "allow_late_submission":false }' curl --fail-with-body -X POST "$GO_API/assignments/<assignment-uuid>/submissions/" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H 'Content-Type: application/json' \ --data '{ "response_text":"My completed report", "attachment":"uploads/42/answer.pdf", "status":"submitted" }'

The assignment path’s class UUID is authoritative. Submission status must be draft or submitted; a grade request uses POST /assignments/submissions/{submission_uuid}/grade/ with { "score":85, "feedback":"Strong reasoning", "action":"grade" }, where action is only grade or return.

AI indexer and gateway agent calls

Force a private indexer retry

Source: indexer FastAPI routes

curl --fail-with-body -X POST "$INDEXER/v1/index/uploads/$UPLOAD_ID" \ -H "Authorization: Bearer $INDEXER_TOKEN" \ -H 'Content-Type: application/json' \ --data '{"force":true}' curl --fail-with-body -X POST "$INDEXER/v1/index/process-due" \ -H "Authorization: Bearer $INDEXER_TOKEN" \ -H 'Content-Type: application/json' \ --data '{"limit":100,"include_done":false}'

process-due.limit must be an integer from 1 through 1000; FastAPI emits 422 for an invalid body. Protected calls emit 401 with { "detail":"Invalid service token" }. Unknown job status is 404 with { "detail":"AI processing job not found" }; unavailable runtime dependencies return 503.

Ask the FastMCP gateway to insert a share

Source: ProxyRequest

curl --fail-with-body -X POST "$AGENT_GATEWAY/v1/proxy" \ -H "Authorization: Bearer $GATEWAY_TOKEN" \ -H 'Content-Type: application/json' \ --data '{ "method":"POST", "path":"/api/v1/sharing/", "user_token":"<end-user Kibegi access JWT>", "params":null, "body":{"file_code":"ABC123","shared_with_id":42,"message":"Please review"}, "confirm":true }'

The gateway returns a wrapper even when Go rejects the downstream operation:

{ "http_status": 201, "response": { "success": true, "message": "File shared successfully. Recipient will be notified.", "data": {}, "errors": null } }

An unconfirmed non-GET request fails before Go is called with 400 and { "detail":"Mutation requires confirm=true" }. A path outside the exposed /api/v1/ namespaces fails with 400 and { "detail":"Path is outside the exposed Kibegi API namespace" }. The optional gateway service token is separate from the user JWT; use the user JWT for every protected domain operation.

Upload through the typed MCP tool

The only safe agent file-insertion method is the typed upload_file tool. Send this tool argument object, not the JSON proxy route:

{ "file_name":"week-01-notes.pdf", "content_base64":"JVBERi0xLjQK…", "class_id":"11111111-2222-3333-4444-555555555555", "user_token":"<end-user Kibegi access JWT>", "confirm":true }

The tool validates base64 and 50 MiB before it constructs the Go multipart request. A successful typed download_file returns { "http_status", "file_name", "content_type", "content_base64" }; the equivalent direct Go download returns bytes instead.

Agent implementation checklist

An agent should first obtain/receive an access JWT, read the target resource, present a mutation preview, and only then submit the exact payload with confirm:true through the gateway. Handle http_status from the gateway wrapper before inspecting response.success. For direct Go calls, handle status and envelope together. Treat 400, 403, and 409 as corrective user/action feedback; treat 401 as an authentication flow; bound retries to safe GET operations or clearly idempotent job-recovery calls.

Last updated on