Skip to content

API reference

import { Tabs, TabItem } from “@astrojs/starlight/components”;

All endpoints live on your customer Function App at https://pocai-fa-{stack-hash}.azurewebsites.net/api/. Authentication varies by endpoint — see each entry.

Anonymous endpoints

GET /api/health

Liveness probe + minimal deployment metadata.

{
"ok": true,
"deploymentId": "pocai-...",
"marketplaceSubscriptionId": "...",
"version": "phase24-synctrigger",
"startedAt": "2026-...",
"bootstrap": { "attempted": true, "result": "succeeded" },
"seat": { "activeSessionCount": 0, "lastReportedQuantity": 0 },
"tokens": { ... }
}

GET /api/plan

Current plan + seat quota + grace state. Used by the dashboard JS.

{
"planId": "growth",
"planDisplayName": "Growth",
"seatQuota": 7,
"seatsUsed": 4,
"exceeded": false,
"daysOverQuota": 0,
"gracePeriodDays": 7,
"blocked": false,
"upgradeUrl": "https://portal.azure.com/..."
}

POST /api/chat

Visitor sends a chat message. Authentication: visitor JWT in Authorization: Bearer (issued by the widget’s /api/widget.js bootstrap).

Body:

{ "message": "Hi, I need help with...", "sessionId": "<uuid optional>" }

When the session is bot-handled: returns 200 with the bot’s reply. When the session has been claimed by an agent: returns 202 queued-for-agent and broadcasts the visitor message to the agent via SignalR.

POST /api/negotiate

SignalR negotiate for visitors. Returns connection info bound to userId = sessionId. Anonymous; the widget posts here.

Admin-key gated endpoints

All require ?code=<admin-key> query param, Authorization: Bearer <key> header, OR a valid session cookie.

EndpointReturns
GET /api/dashboardHTML admin dashboard
GET /api/cost?window=24h|7d&bucketHours=NTime-bucketed cost data
GET /api/sessions?sortBy=cost&limit=NTop sessions list
GET /api/sessions/search?q=...Full-text search across messages
GET /api/sessions/{id}/transcriptFull transcript for one session
POST /api/ops/rotate-keyGenerate + return new admin key
GET /api/teams-app.zipPer-deployment Teams app .zip download
GET /api/teams-setupTeams setup wizard HTML

Agent endpoints (Teams SSO gated)

All require Authorization: Bearer <Teams-SSO-token>. The customer-runtime validates the JWT against your AAD app (AAD_APP_CLIENT_ID + AAD_APP_TENANT_ID).

GET /api/agent/me

Returns the authenticated agent’s normalized claims:

{ "oid": "...", "upn": "agent@tenant.onmicrosoft.com", "email": "...", "tenantId": "..." }

POST /api/agent/negotiate

SignalR negotiate for agents. Returns connection info bound to userId = agent.oid.

GET /api/agent/sessions[?status=&claimedBy=&limit=]

Lists chat sessions visible to agents. Filters:

  • statusopen, human_requested, claimed, closed
  • claimedBy — agent oid, or me to filter to own claimed sessions
  • limit — 1-200, default 50

POST /api/agent/sessions/{id}/claim

Claim a session. Seat-gated:

  • Under quota → 200 with the updated session
  • Grace period → 200 + quotaStatus block in response body
  • Post-grace + new agent → 403 { error: "seat-quota-exceeded", upgradeUrl, ... }
  • Already claimed by another agent → 409
  • Already claimed by caller → 200 { alreadyClaimed: true } (idempotent)

POST /api/agent/sessions/{id}/message

Send a message from the owning agent. Body: { "content": "string (1-4000 chars)" }. Broadcasts to the visitor via SignalR.

  • Not the owning agent → 403
  • Session closed → 409

POST /api/agent/sessions/{id}/close

Close a session. Owning agent only.

ISV control plane endpoints

These live on the ISV side at https://pocai-isv-cp.azurewebsites.net/api/ and are mostly invoked by Microsoft Marketplace, Microsoft Graph, or our own orchestrator. The public ones:

  • GET /api/plans — list all plans (Start / Growth / Professional)
  • GET /api/plans/{planId} — single plan details

Both are anonymous with 5-minute cache.