AiGov API Documentation
Integrate AI governance workflows into your tools and processes. Manage initiatives, automate technology intake, query your tech inventory, and build custom dashboards — all through a secure, RESTful API.
Overview
The AiGov API is organized around REST principles. It accepts JSON request bodies, returns JSON responses, and uses standard HTTP response codes.
RESTful
Predictable, resource-oriented URLs with standard HTTP verbs.
Secure
TLS-only with application-level tenant isolation and role-based access control.
Multi-tenant
Tenant isolation enforced at the database level on every request.
Authentication
All API requests require authentication. AiGov uses Auth.js v5 with Microsoft Entra ID (Azure AD) OAuth 2.0. Browser clients authenticate via session cookies; server-to-server integrations use Bearer tokens from the /api/auth endpoints.
# Browser clients are automatically authenticated via HTTP-only session cookies
# set by the Auth.js /api/auth/* endpoints. No manual header needed.
Cookie: authjs.session-token=<session-token>// Browser: redirect to Microsoft Entra ID login
import { signIn } from 'next-auth/react'
await signIn('microsoft-entra-id', {
redirectTo: '/dashboard'
})
// Server-side: get session in API routes or server actions
import { auth } from '@/lib/auth/auth'
const session = await auth()
const userId = session?.user?.idKeep your tokens secure
Never expose your AUTH_SECRET or AUTH_MICROSOFT_ENTRA_ID_SECRET in client-side code. Session tokens are HTTP-only cookies and cannot be accessed via JavaScript. Server-side integrations should use environment variables for secrets.
Base URL
All API requests are made against your AiGov deployment URL. The API is served through Next.js API routes and server actions.
# REST API (v1)
https://portal.aigov.technostica.net/api/v1/
# Auth.js Endpoints
https://portal.aigov.technostica.net/api/auth/signin
https://portal.aigov.technostica.net/api/auth/signout
https://portal.aigov.technostica.net/api/auth/session
# Chat (SSE streaming)
https://portal.aigov.technostica.net/api/chat
# Text-to-Speech
https://portal.aigov.technostica.net/api/tts
# Audit Log Export
https://portal.aigov.technostica.net/api/export/audit-logsRate Limits
Rate limits protect against abuse and ensure fair usage for all tenants.
| Endpoint | Limit | Window |
|---|---|---|
| Intake Chat Messages | 50 requests | Per user, per hour |
| Initiative Creation | 10 requests | Per user, per day |
| REST API (general) | 1,000 requests | Per user, per hour |
| Audit Log Export | 10 requests | Per admin, per hour |
{
"error": "Rate limit exceeded. Please try again later.",
"remaining": 0
}Errors
AiGov uses conventional HTTP status codes to indicate the success or failure of a request.
| Code | Status | Description |
|---|---|---|
| 200 | OK | Request succeeded. |
| 201 | Created | Resource created successfully. |
| 400 | Bad Request | Invalid request body or parameters. |
| 401 | Unauthorized | Missing or invalid authentication token. |
| 403 | Forbidden | Insufficient role or permissions. |
| 404 | Not Found | Resource does not exist or is inaccessible. |
| 409 | Conflict | Resource already exists or state conflict. |
| 429 | Too Many Requests | Rate limit exceeded. |
| 500 | Internal Server Error | Something went wrong on our end. |
{
"error": "A human-readable error message",
"code": "ERROR_CODE",
"details": "Additional context when available"
}Initiatives
Initiatives are the core resource in AiGov. They represent technology requests that move through the governance workflow — from intake through functional review and enterprise approval.
The Initiative Object
{
"id": "uuid",
"tenant_id": "uuid",
"submitter_id": "uuid",
"title": "Slack for Engineering",
"vendor": "Slack Technologies",
"licensing_model": "SaaS per-user subscription",
"deployment_model": "cloud", // "cloud" | "on_prem" | "hybrid"
"data_handling": ["internal-only"],
"user_scope": "employee", // "employee" | "customer" | "both"
"queue_id": "uuid",
"problem_statement": "Need real-time messaging for distributed teams",
"business_value": "Improve cross-team communication efficiency by 40%",
"estimated_users": 250,
"urgency": "quarter", // "immediate" | "quarter" | "next_fiscal_year"
"current_stage": "functional_review",// "intake" | "functional_review" | "enterprise_workflow"
"current_status": "Pending Review",
"matched_tool_id": null,
"created_tool_id": null,
"intake_document": { ... },
"created_at": "2026-03-01T12:00:00Z",
"updated_at": "2026-03-01T14:30:00Z"
}/api/v1/initiativesSession CookieList initiatives for the authenticated user. Use ?scope=enterprise for all tenant initiatives, or ?queue_id=<id> for a specific queue. Default returns the user's own initiatives.
| Parameter | Type | Required | Description |
|---|---|---|---|
scope | string | Optional | "enterprise" to list all tenant initiatives |
queue_id | uuid | Optional | Filter by functional queue |
// List my initiatives
const res = await fetch('/api/v1/initiatives', { credentials: 'include' })
const { data } = await res.json()
// List all enterprise initiatives
const all = await fetch('/api/v1/initiatives?scope=enterprise', { credentials: 'include' })
// Get a single initiative
const detail = await fetch('/api/v1/initiatives/550e8400-...', { credentials: 'include' })
const { data: initiative } = await detail.json()/api/v1/initiativesSession CookieCreate a new initiative in Drafting status. Typically created automatically when a user starts the intake chatbot.
const res = await fetch('/api/v1/initiatives', {
method: 'POST',
credentials: 'include'
})
const { data } = await res.json() // { id: "uuid", ... }/api/v1/initiatives/:id/transitionSession Cookie (role-dependent)Transition an initiative to a new status. Validates against the workflow state machine. Every transition requires a mandatory comment.
| Parameter | Type | Required | Description |
|---|---|---|---|
newStatus | string | Required | Target status (validated by state machine) |
comment | string | Required | Mandatory explanation for the transition |
const res = await fetch('/api/v1/initiatives/550e8400-.../transition', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({
newStatus: 'Approved for Prototype',
comment: 'Meets all requirements. Approved for pilot deployment.'
})
})
const result = await res.json()/api/v1/initiatives/:idSession Cookie (submitter only)Delete a draft initiative. Only allowed when current_status is "Drafting" and the request is made by the submitter.
curl -X DELETE 'https://portal.aigov.technostica.net/api/v1/initiatives/<id>' \
-H 'Cookie: authjs.session-token=<token>'Intake Chat
The AI-powered intake chatbot conducts conversational interviews to collect initiative information. It streams responses via Server-Sent Events (SSE).
/api/chatBearer TokenSend a message to the intake chatbot. Returns a streaming SSE response with text deltas, tool results, and completion events.
| Parameter | Type | Required | Description |
|---|---|---|---|
message | string | Required | The user message to send to the chatbot |
initiativeId | uuid | Required | ID of the initiative this conversation belongs to |
const response = await fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
message: 'I need a project management tool for our engineering team',
initiativeId: '550e8400-e29b-41d4-a716-446655440000'
})
})
const reader = response.body!.getReader()
const decoder = new TextDecoder()
while (true) {
const { done, value } = await reader.read()
if (done) break
const chunk = decoder.decode(value)
for (const line of chunk.split('\n')) {
if (line.startsWith('data: ')) {
const event = JSON.parse(line.slice(6))
if (event.type === 'text') process.stdout.write(event.text)
if (event.type === 'done') console.log('\n--- Done ---')
}
}
}SSE Event Types
| Event Type | Payload |
|---|---|
text | Streaming text delta from the AI assistant |
tool_result | Result from a tool call (inventory search, web search, submission) |
user_message_id | Persisted user message ID for client tracking |
done | Stream complete; includes assistant_message_id |
error | Error message if something went wrong |
data: {"type":"user_message_id","id":"msg_abc123"}
data: {"type":"text","text":"I'd be happy to help you find a project management"}
data: {"type":"text","text":" tool. Let me search your organization's inventory..."}
data: {"type":"tool_result","tool":"search_tech_inventory","results":[...]}
data: {"type":"text","text":"I found a few existing tools..."}
data: {"type":"done","assistant_message_id":"msg_def456"}Available Chat Tools
The chatbot has access to the following tools that it invokes automatically during conversations:
update_titleSets the initiative title based on conversation context
search_tech_inventorySearches the org tech inventory for existing solutions
web_searchSearches the web for vendor/tool information via Tavily
search_initiativesSearches existing initiatives to detect in-flight duplicates
submit_initiativeSubmits the initiative after user confirmation
resolve_initiativeResolves by connecting user to existing tool owner
/api/v1/initiatives/:id/chatSession CookieRetrieve the chat message history for an initiative. Returns all user, assistant, and system (tool result) messages in chronological order.
const res = await fetch('/api/v1/initiatives/550e8400-.../chat', {
credentials: 'include'
})
const { data: messages } = await res.json()
// messages: [{ role, content, created_at }, ...]Documents
Upload and manage file attachments on initiatives. Supports PDF, DOCX, XLSX, PNG, JPG, and SVG files up to 10 MB each (max 5 per submission). Files are stored in Google Cloud Storage.
/api/v1/initiatives/:id/documentsSession CookieList all documents attached to an initiative.
const res = await fetch('/api/v1/initiatives/<id>/documents', {
credentials: 'include'
})
const { data: docs } = await res.json()
// docs: [{ id, file_name, file_type, file_size, uploaded_at }, ...]/api/v1/initiatives/:id/documentsSession Cookie (role-dependent)Upload a document to an initiative. Send as multipart/form-data. Upload permissions are stage-based (see PRD section 4.8).
| Parameter | Type | Required | Description |
|---|---|---|---|
file | File | Required | The file to upload (max 10 MB) |
const formData = new FormData()
formData.append('file', fileInput.files[0])
const res = await fetch('/api/v1/initiatives/<id>/documents', {
method: 'POST',
credentials: 'include',
body: formData
})
const { data } = await res.json()/api/v1/initiatives/:id/documents/:docIdSession Cookie (uploader or Admin)Delete a document from an initiative.
Investment Asks
Manage resource requests (human capital) and financial requests (line-item costs) attached to initiatives. These are added by Function Leads when approving for scaling.
/api/v1/initiatives/:id/resourcesSession Cookie (Function Lead / Admin)Add a resource request (human capital) to an initiative.
| Parameter | Type | Required | Description |
|---|---|---|---|
role | string | Required | Job title or function needed |
quantity | number | Required | Number of people |
duration_months | number | Required | Duration in months |
location | string | Required | On-site, remote, or offshore |
pay_rate | number | Required | Pay rate amount |
pay_frequency | enum | Required | "hourly", "monthly", or "annual" |
const res = await fetch('/api/v1/initiatives/<id>/resources', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({
role: 'Cloud Engineer',
quantity: 2,
duration_months: 6,
location: 'Remote',
pay_rate: 85,
pay_frequency: 'hourly'
})
})/api/v1/initiatives/:id/resourcesSession Cookie (Function Lead / Admin)Delete a resource request by ID.
| Parameter | Type | Required | Description |
|---|---|---|---|
resourceId | uuid | Required | ID of the resource request to delete |
/api/v1/initiatives/:id/financialsSession Cookie (Function Lead / Admin)Add a financial request (line-item cost) to an initiative.
| Parameter | Type | Required | Description |
|---|---|---|---|
category | enum | Required | "licensing", "infrastructure", "implementation", "training", or "other" |
description | string | Required | Details of the cost item |
amount | number | Required | Estimated cost amount |
frequency | enum | Required | "one_time", "monthly", or "annual" |
const res = await fetch('/api/v1/initiatives/<id>/financials', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({
category: 'licensing',
description: 'Annual SaaS license for 250 seats',
amount: 45000,
frequency: 'annual'
})
})/api/v1/initiatives/:id/financialsSession Cookie (Function Lead / Admin)Delete a financial request by ID.
| Parameter | Type | Required | Description |
|---|---|---|---|
financialId | uuid | Required | ID of the financial request to delete |
Tech Inventory
The tech inventory tracks all approved and active technology tools across the organization. It supports full-text and semantic search.
/api/v1/inventorySession CookieList tech inventory items for the tenant. Supports search by tool name, vendor, and description using pg_trgm fuzzy matching.
| Parameter | Type | Required | Description |
|---|---|---|---|
search | string | Optional | Search query (fuzzy matches tool_name, vendor, description) |
status | string | Optional | "active", "deprecated", or "under_review" |
// List all inventory items
const res = await fetch('/api/v1/inventory', { credentials: 'include' })
const { data } = await res.json()
// Search with fuzzy matching
const search = await fetch('/api/v1/inventory?search=project+management', {
credentials: 'include'
})
const { data: results } = await search.json()/api/v1/inventorySession Cookie (Admin)Create a new tech inventory entry. Admin role required. Items are also auto-created when initiatives reach Enterprise Approved status.
| Parameter | Type | Required | Description |
|---|---|---|---|
tool_name | string | Required | Name of the tool |
vendor | string | Required | Vendor name |
category | string | Required | Tool category |
department | string | Required | Owning department |
description | string | Optional | Tool description |
status | enum | Optional | "active", "deprecated", or "under_review" |
const res = await fetch('/api/v1/inventory', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({
tool_name: 'Jira',
vendor: 'Atlassian',
category: 'Engineering',
department: 'Technology',
description: 'Project tracking and agile management',
status: 'active'
})
})
const { data } = await res.json()/api/v1/inventory/:idSession Cookie (Admin)Update an existing tech inventory entry. Admin role required.
curl -X PATCH 'https://portal.aigov.technostica.net/api/v1/inventory/<id>' \
-H 'Content-Type: application/json' \
-H 'Cookie: authjs.session-token=<token>' \
-d '{"status": "deprecated"}'/api/v1/inventory/:idSession Cookie (Admin)Delete a tech inventory entry. Admin role required.
Functional Queues
Functional queues route initiatives to the appropriate department for review. Each queue has assigned function leads who manage incoming submissions.
/api/v1/queuesSession CookieList all functional queues for the tenant.
{
"id": "uuid",
"tenant_id": "uuid",
"name": "Engineering",
"description": "Engineering tools and infrastructure requests",
"webhook_url": "https://outlook.office.com/webhook/...",
"is_active": true,
"created_at": "2026-01-15T09:00:00Z",
"updated_at": "2026-01-15T09:00:00Z"
}const res = await fetch('/api/v1/queues', { credentials: 'include' })
const { data: queues } = await res.json()
for (const q of queues) {
console.log(q.name, q.is_active ? '(active)' : '(inactive)')
}/api/v1/queuesSession Cookie (Admin)Create a new functional queue.
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Required | Queue name (e.g., "Engineering", "Marketing") |
description | string | Optional | Queue description (used by AI for routing context) |
webhook_url | string | Optional | Microsoft Teams webhook URL for new submission notifications |
is_active | boolean | Optional | Whether the queue accepts submissions (default: true) |
const res = await fetch('/api/v1/queues', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ name: 'Regulatory', description: 'Compliance and regulatory tools' })
})
const { data } = await res.json()/api/v1/queues/:idSession Cookie (Admin)Update a functional queue.
curl -X PATCH 'https://portal.aigov.technostica.net/api/v1/queues/<id>' \
-H 'Content-Type: application/json' \
-H 'Cookie: authjs.session-token=<token>' \
-d '{"is_active": false}'/api/v1/queues/:idSession Cookie (Admin)Deactivate a functional queue (soft delete).
Reviews & Comments
Comments track all feedback, status transitions, and review decisions on initiatives. Review checklists track security and legal review completion.
/api/v1/initiatives/:id/commentsSession CookieList all comments on an initiative, including status change records and review feedback.
{
"id": "uuid",
"initiative_id": "uuid",
"author_id": "uuid",
"content": "Approved — meets all security requirements.",
"review_type": "security", // "security" | "legal" | null
"traffic_light": "green", // "green" | "yellow" | "red" | null
"status_change_from": "Pending Review",
"status_change_to": "Approved for Prototype",
"created_at": "2026-03-02T10:00:00Z"
}const res = await fetch('/api/v1/initiatives/<id>/comments', { credentials: 'include' })
const { data: comments } = await res.json()/api/v1/initiatives/:id/commentsSession Cookie (role-dependent)Add a comment or review decision to an initiative.
| Parameter | Type | Required | Description |
|---|---|---|---|
content | string | Required | Comment text or review feedback |
review_type | enum | Optional | "security" or "legal" for review comments |
traffic_light | enum | Optional | "green", "yellow", or "red" risk assessment |
status_change_to | string | Optional | New status if this comment triggers a transition |
const res = await fetch('/api/v1/initiatives/<id>/comments', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({
content: 'Approved — meets all security requirements.',
review_type: 'security',
traffic_light: 'green'
})
})/api/v1/initiatives/:id/reviewsSession CookieGet security and legal review checklists for an initiative.
{
"id": "uuid",
"initiative_id": "uuid",
"review_type": "security",
"is_completed": true,
"traffic_light": "green",
"reviewer_id": "uuid",
"completed_at": "2026-03-02T11:00:00Z"
}curl 'https://portal.aigov.technostica.net/api/v1/initiatives/<id>/reviews' \
-H 'Cookie: authjs.session-token=<token>'/api/v1/reviews/pendingSession CookieGet all reviews pending for the current user across all initiatives.
curl 'https://portal.aigov.technostica.net/api/v1/reviews/pending' \
-H 'Cookie: authjs.session-token=<token>'Audit Logs
Immutable audit trail of all actions in the platform. Every status change, review, and submission is recorded with full context.
/api/export/audit-logs?format=jsonSession Cookie (Admin)Query audit logs for the tenant. Returns JSON when format=json is specified, or CSV by default.
{
"id": "uuid",
"initiative_id": "uuid",
"actor_id": "uuid",
"action": "status_change",
"details": {
"from": "Drafting",
"to": "Pending Review",
"via": "chatbot_submission"
},
"created_at": "2026-03-01T14:30:00Z"
}/api/export/audit-logsSession Cookie (Admin)Export all audit logs. Returns CSV by default, or JSON when ?format=json is appended. Headers: id, initiative_id, actor_id, action, details, created_at.
const response = await fetch('/api/export/audit-logs?format=json', {
credentials: 'include'
})
const logs = await response.json()
console.log(`Found ${logs.length} audit log entries`)Notifications
In-app and email notifications for status changes, new submissions, review requests, and tool owner connections.
/api/v1/notificationsSession CookieRetrieve notifications for the authenticated user. Use ?count_only=true to get just the unread count. Supports ?limit= for pagination.
| Parameter | Type | Required | Description |
|---|---|---|---|
limit | number | Optional | Max notifications to return |
count_only | boolean | Optional | Return only unread count |
{
"id": "uuid",
"recipient_id": "uuid",
"initiative_id": "uuid",
"type": "status_change", // "status_change" | "new_submission" |
// "review_required" | "mention" | "connect_to_owner"
"message": "Your initiative \"Slack for Engineering\" moved to Pending Review",
"read": false,
"email_sent": true,
"created_at": "2026-03-01T14:30:00Z"
}// Get notifications
const res = await fetch('/api/v1/notifications?limit=20', { credentials: 'include' })
const { data } = await res.json()
// Get unread count only
const count = await fetch('/api/v1/notifications?count_only=true', { credentials: 'include' })
const { data: unreadCount } = await count.json()/api/v1/notificationsSession CookieMark one or more notifications as read.
| Parameter | Type | Required | Description |
|---|---|---|---|
id | uuid | Required | Notification ID to mark as read |
curl -X PATCH 'https://portal.aigov.technostica.net/api/v1/notifications' \
-H 'Content-Type: application/json' \
-H 'Cookie: authjs.session-token=<token>' \
-d '{"id": "<notification-id>"}'/api/v1/notificationsSession CookieClear all notifications for the authenticated user.
curl -X DELETE 'https://portal.aigov.technostica.net/api/v1/notifications' \
-H 'Cookie: authjs.session-token=<token>'Notification Types
status_change — Initiative status was updated
new_submission — New initiative submitted to a queue
review_required — Security or legal review needed
mention — User was mentioned in a comment
connect_to_owner — Someone wants to connect about your tool
Users & Roles
Manage user profiles and role-based access control. AiGov supports six roles with granular permissions.
| Role | Permissions |
|---|---|
public | Submit initiatives, view own submissions, chat with intake bot |
function_lead | Review queue submissions, approve/reject at functional level, manage queue |
enterprise_lead | Enterprise-stage reviews, scaling decisions, final approvals |
security_reviewer | Security review checklists, risk assessments, traffic light ratings |
legal_reviewer | Legal review checklists, compliance assessments, traffic light ratings |
admin | Full tenant management: users, queues, audit logs, settings |
/api/v1/usersSession Cookie (Admin)List user profiles for the tenant with their assigned roles. Supports search and role filtering.
| Parameter | Type | Required | Description |
|---|---|---|---|
search | string | Optional | Search by name or email |
role | string | Optional | Filter by role |
{
"id": "uuid",
"tenant_id": "uuid",
"email": "jane@example.com",
"full_name": "Jane Smith",
"avatar_url": "https://...",
"notification_preference": "per_event", // "per_event" | "daily_digest"
"created_at": "2026-01-01T00:00:00Z",
"updated_at": "2026-03-01T00:00:00Z"
}const res = await fetch('/api/v1/users?search=jane', { credentials: 'include' })
const { data: users } = await res.json()/api/v1/users/:idSession Cookie (Admin)Get a single user profile with role details.
{
"id": "uuid",
"user_id": "uuid",
"tenant_id": "uuid",
"role": "function_lead",
"queue_id": "uuid", // null for non-queue-specific roles
"assigned_at": "2026-01-15T00:00:00Z"
}/api/v1/users/:id/rolesSession Cookie (Admin)Assign a role to a user.
| Parameter | Type | Required | Description |
|---|---|---|---|
role | enum | Required | One of the six available roles |
queue_id | uuid | Optional | Queue ID (required for function_lead role) |
const res = await fetch('/api/v1/users/<user-id>/roles', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ role: 'function_lead', queue_id: '<queue-id>' })
})/api/v1/users/:id/rolesSession Cookie (Admin)Revoke a role from a user.
| Parameter | Type | Required | Description |
|---|---|---|---|
role | enum | Required | Role to revoke |
queue_id | uuid | Optional | Queue ID (for function_lead role) |
/api/v1/profileSession CookieGet the current user's profile.
curl 'https://portal.aigov.technostica.net/api/v1/profile' \
-H 'Cookie: authjs.session-token=<token>'/api/v1/profileSession CookieUpdate the current user's profile (notification preferences, etc.).
curl -X PATCH 'https://portal.aigov.technostica.net/api/v1/profile' \
-H 'Content-Type: application/json' \
-H 'Cookie: authjs.session-token=<token>' \
-d '{"notification_preference": "daily_digest"}'Dashboard Analytics
REST endpoints that power the analytics dashboard. Use these to build custom reports and integrations.
/api/v1/dashboardSession CookieFetch dashboard analytics. Returns all sections by default, or use ?section= to fetch a specific one. Supports ?months= for time range.
| Parameter | Type | Required | Description |
|---|---|---|---|
section | string | Optional | "by-function", "funnel", "volume", or "approval". Omit for all. |
months | number | Optional | Number of months for trends (default: 12) |
// Get all dashboard data
const res = await fetch('/api/v1/dashboard', { credentials: 'include' })
const { data } = await res.json()
console.log(data.byFunction, data.funnel, data.volume, data.approval)
// Get a specific section
const volume = await fetch('/api/v1/dashboard?section=volume&months=6', {
credentials: 'include'
})
const { data: trends } = await volume.json(){
"success": true,
"data": {
"byFunction": [
{ "queue_name": "Engineering", "count": 45, "statuses": {...} },
{ "queue_name": "Marketing", "count": 32, "statuses": {...} }
],
"funnel": [
{ "stage": "drafting", "count": 142 },
{ "stage": "submitted", "count": 130 }
],
"volume": [
{ "month": "2026-01", "intake": 12, "functional": 8, "enterprise": 3 }
],
"approval": [
{ "month": "2026-01", "approved": 5, "rejected": 2, "rate": 0.71 }
]
}
}Text-to-Speech
Convert text to audio using Google Cloud Text-to-Speech. Used by the blog read-aloud feature. Rate limited to 10 requests per minute per IP.
/api/ttsNo authentication requiredConvert text to speech audio. Returns an MP3 audio buffer. Automatically chunks long text to stay within Google Cloud TTS limits.
| Parameter | Type | Required | Description |
|---|---|---|---|
text | string | Required | The text to convert to speech |
const res = await fetch('/api/tts', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text: 'Hello, welcome to AiGov.' })
})
const audioBlob = await res.blob()
const audioUrl = URL.createObjectURL(audioBlob)
const audio = new Audio(audioUrl)
audio.play()Real-time Updates
AiGov uses polling-based real-time updates for notifications and data changes. The intake chat uses Server-Sent Events (SSE) for streaming AI responses.
import { useNotifications } from '@/hooks/use-notifications'
// Polls every 10 seconds for new notifications
useNotifications((notification) => {
console.log('New notification:', notification.message)
// Show toast, update badge count, etc.
})
// Generic polling hook for data changes
import { useRealtime } from '@/hooks/use-realtime'
useRealtime({
table: 'initiatives',
event: '*',
interval: 5000,
onData: (payload) => {
router.refresh()
}
})Real-time Capabilities
SSE streaming — AI chat responses stream in real-time via /api/chat
Notification polling — New notifications detected every 10 seconds
Data polling — Configurable interval polling for any table changes
Email notifications — Instant email delivery via Resend on status changes and @mentions
Teams webhooks — Per-queue Microsoft Teams Adaptive Card notifications for new submissions
SDKs & Libraries
AiGov is built with Next.js server actions and API routes. Use these libraries for integration.
TypeScript (Server Actions)
next-auth + drizzle-ormnpm install next-auth@beta drizzle-ormPython (HTTP Client)
requestspip install requestsCLI (cURL)
curlBuilt into macOS/Linux; Windows: winget install curlDatabase (Direct)
psql / pgpsql postgresql://user:pass@host:5432/aigov// Authentication is handled by Auth.js with Microsoft Entra ID
import { signIn } from 'next-auth/react'
await signIn('microsoft-entra-id')
// List initiatives
const initiatives = await fetch('/api/v1/initiatives', { credentials: 'include' })
const { data } = await initiatives.json()
// Search tech inventory
const search = await fetch('/api/v1/inventory?search=project+management', {
credentials: 'include'
})
const { data: results } = await search.json()
// Get dashboard analytics
const dash = await fetch('/api/v1/dashboard', { credentials: 'include' })
const { data: dashboard } = await dash.json()
console.log(dashboard.byFunction, dashboard.volume)Need Help?
Need help integrating with the AiGov API or building custom governance workflows? Reach out to the Technostica AiGov team.