This document defines the HTTP API surface that anchors:
- P1 · Session Lifecycle (session creation and lookup)
- P5 · Billing & Entitlement (checkout and payment notification)
It is MVP-faithful:
- All endpoints and fields exist in the running MVP backend
- No additional capabilities are introduced beyond current behavior
- Base path:
/api - Minimal endpoint set:
POST /api/session– create analysis session (returnssessionId)GET /api/session/:sessionId– inspect session and obtainresultKeyPOST /api/checkout– create a checkout session for a topicPOST /api/webhook– payment provider webhook (server-to-server only)
- This channel never delivers analysis content; all content flows via C1 stream.
- Session creation and minimal inspection
- Payment initiation via an external checkout session
- Payment completion notification via a payment provider webhook
- User account management or authentication
- Analysis execution or result delivery
- Generic billing abstraction beyond the current payment provider integration
- Multi-tenant or multi-project routing
| Method | Path | Role |
|---|---|---|
| POST | /api/session |
Create analysis session |
| GET | /api/session/:sessionId |
Inspect session, get resultKey |
| POST | /api/checkout |
Create payment provider checkout session |
| POST | /api/webhook |
Payment provider webhook endpoint |
Create an ephemeral analysis session and register canonical analysis input.
Content-Type: application/json
{
"input": {
"...": "domain-specific analysis input (omitted in this contract)"
}
}- Request body MUST be a JSON object.
- Field-level schema is domain-specific and intentionally omitted here.
- The backend treats this payload as the canonical input bound to the session.
{
"code": 200,
"data": {
"sessionId": "uuid-value",
"message": "session created"
}
}HTTP 400:
{
"code": 400,
"message": "invalid or incomplete input"
}Validation messages are implementation-specific; only the shape is normative.
HTTP 500:
{
"code": 500,
"message": "internal server error"
}Inspect an existing session and obtain identifiers needed by the streaming layer.
Path parameter:
sessionId– UUID returned byPOST /api/session
{
"code": 200,
"data": {
"sessionId": "uuid-value",
"resultKey": "opaque_key",
"status": "pending",
"progress": 0,
"paid": false,
"createdAt": 1710000000000,
"topics": []
}
}Fields other than sessionId and resultKey are implementation details and may evolve.
HTTP 404:
{
"code": 404,
"message": "session not found or expired"
}Initiate a payment provider checkout session for a given session and topic.
Content-Type: application/json
{
"sessionId": "uuid-value",
"topic": "topicA"
}sessionId(string, required) – existing session identifiertopic(string, required) – analysis topic label
{
"code": 200,
"message": "checkout session created",
"data": {
"checkoutUrl": "https://checkout.example.com/...",
"providerSessionId": "opaque-session-id"
}
}HTTP 400 or 404:
{
"code": 400,
"message": "sessionId and topic are required"
}or:
{
"code": 404,
"message": "session not found or expired"
}HTTP 500:
{
"code": 500,
"message": "failed to create checkout session"
}Payment provider webhook endpoint. This is not called by clients; it is invoked by the payment provider.
- Expects a provider-specific signature header and raw JSON body
- Verifies signature using the configured webhook secret
- On a successful checkout completion event:
- Extracts
sessionIdandtopicfromevent.data.object.metadata - Marks the corresponding topic as paid in the in-memory session store
- Marks payment notification status for that topic as pending
- Attempts a best-effort push to any still-open WebSocket client via
notifyPaymentSuccess(sessionId, topic); if no client is connected, only the stored payment state is updated
- Extracts
Response shape:
{
"received": true
}On signature failure, the endpoint returns HTTP 400 with a plain-text error message.
Health endpoints are intentionally out of scope for this contract.