Files

882 lines
25 KiB
YAML
Raw Permalink Normal View History

2026-03-13 23:21:55 +00:00
openapi: 3.1.0
info:
# Do not change the title, if the title changes, the import paths will be broken
title: Api
version: 0.1.0
description: API specification
servers:
- url: /api
description: Base API path
tags:
- name: health
description: Health operations
Task #3: MVP API — payment-gated jobs + demo endpoint OpenAPI spec (lib/api-spec/openapi.yaml) - Added POST /jobs, GET /jobs/{id}, GET /demo endpoints - Added schemas: CreateJobRequest, CreateJobResponse, JobStatusResponse, InvoiceInfo, JobState, DemoResponse, ErrorResponse - Ran codegen: generated CreateJobBody, GetJobResponse, RunDemoQueryParams etc. Jobs router (artifacts/api-server/src/routes/jobs.ts) - POST /jobs: validates body, creates LNbits eval invoice, inserts job + invoice in a DB transaction, returns { jobId, evalInvoice } - GET /jobs/:id: fetches job, calls advanceJob() helper, returns state- appropriate payload (eval/work invoice, reason, result, errorMessage) - advanceJob() state machine: - awaiting_eval_payment: checks LNbits, atomically marks paid + advances state via optimistic WHERE state='awaiting_eval_payment'; runs AgentService.evaluateRequest, branches to awaiting_work_payment or rejected - awaiting_work_payment: same pattern for work invoice, runs AgentService.executeWork, advances to complete - Any agent/LNbits error transitions job to failed Demo router (artifacts/api-server/src/routes/demo.ts) - GET /demo?request=...: in-memory rate limiter (5 req/hour per IP) - Explicit guard for missing request param (coerce.string() workaround) - Calls AgentService.executeWork directly, returns { result } Dev router (artifacts/api-server/src/routes/dev.ts) - POST /dev/stub/pay/:paymentHash: marks stub invoice paid in-memory - Only mounted when NODE_ENV !== 'production' Route index updated to mount all three routers replit.md: documented full curl flow with all 6 steps, demo endpoint, and dev stub-pay trigger End-to-end verified with curl: - Full flow: create → eval pay → evaluating → work pay → executing → complete - Error cases: 400 on missing body/param, 404 on unknown job
2026-03-18 15:31:26 +00:00
- name: jobs
description: Payment-gated agent job operations (Mode 1 -- per-job)
- name: sessions
description: Pre-funded session balance mode (Mode 2 -- pay once, run many)
Task #3: MVP API — payment-gated jobs + demo endpoint OpenAPI spec (lib/api-spec/openapi.yaml) - Added POST /jobs, GET /jobs/{id}, GET /demo endpoints - Added schemas: CreateJobRequest, CreateJobResponse, JobStatusResponse, InvoiceInfo, JobState, DemoResponse, ErrorResponse - Ran codegen: generated CreateJobBody, GetJobResponse, RunDemoQueryParams etc. Jobs router (artifacts/api-server/src/routes/jobs.ts) - POST /jobs: validates body, creates LNbits eval invoice, inserts job + invoice in a DB transaction, returns { jobId, evalInvoice } - GET /jobs/:id: fetches job, calls advanceJob() helper, returns state- appropriate payload (eval/work invoice, reason, result, errorMessage) - advanceJob() state machine: - awaiting_eval_payment: checks LNbits, atomically marks paid + advances state via optimistic WHERE state='awaiting_eval_payment'; runs AgentService.evaluateRequest, branches to awaiting_work_payment or rejected - awaiting_work_payment: same pattern for work invoice, runs AgentService.executeWork, advances to complete - Any agent/LNbits error transitions job to failed Demo router (artifacts/api-server/src/routes/demo.ts) - GET /demo?request=...: in-memory rate limiter (5 req/hour per IP) - Explicit guard for missing request param (coerce.string() workaround) - Calls AgentService.executeWork directly, returns { result } Dev router (artifacts/api-server/src/routes/dev.ts) - POST /dev/stub/pay/:paymentHash: marks stub invoice paid in-memory - Only mounted when NODE_ENV !== 'production' Route index updated to mount all three routers replit.md: documented full curl flow with all 6 steps, demo endpoint, and dev stub-pay trigger End-to-end verified with curl: - Full flow: create → eval pay → evaluating → work pay → executing → complete - Error cases: 400 on missing body/param, 404 on unknown job
2026-03-18 15:31:26 +00:00
- name: demo
description: Free demo endpoint (rate-limited)
- name: gemini
description: Gemini AI chat and image operations
2026-03-13 23:21:55 +00:00
paths:
/healthz:
get:
operationId: healthCheck
tags: [health]
summary: Health check
description: Returns server health status
responses:
"200":
description: Healthy
content:
application/json:
schema:
$ref: "#/components/schemas/HealthStatus"
Task #3: MVP API — payment-gated jobs + demo endpoint OpenAPI spec (lib/api-spec/openapi.yaml) - Added POST /jobs, GET /jobs/{id}, GET /demo endpoints - Added schemas: CreateJobRequest, CreateJobResponse, JobStatusResponse, InvoiceInfo, JobState, DemoResponse, ErrorResponse - Ran codegen: generated CreateJobBody, GetJobResponse, RunDemoQueryParams etc. Jobs router (artifacts/api-server/src/routes/jobs.ts) - POST /jobs: validates body, creates LNbits eval invoice, inserts job + invoice in a DB transaction, returns { jobId, evalInvoice } - GET /jobs/:id: fetches job, calls advanceJob() helper, returns state- appropriate payload (eval/work invoice, reason, result, errorMessage) - advanceJob() state machine: - awaiting_eval_payment: checks LNbits, atomically marks paid + advances state via optimistic WHERE state='awaiting_eval_payment'; runs AgentService.evaluateRequest, branches to awaiting_work_payment or rejected - awaiting_work_payment: same pattern for work invoice, runs AgentService.executeWork, advances to complete - Any agent/LNbits error transitions job to failed Demo router (artifacts/api-server/src/routes/demo.ts) - GET /demo?request=...: in-memory rate limiter (5 req/hour per IP) - Explicit guard for missing request param (coerce.string() workaround) - Calls AgentService.executeWork directly, returns { result } Dev router (artifacts/api-server/src/routes/dev.ts) - POST /dev/stub/pay/:paymentHash: marks stub invoice paid in-memory - Only mounted when NODE_ENV !== 'production' Route index updated to mount all three routers replit.md: documented full curl flow with all 6 steps, demo endpoint, and dev stub-pay trigger End-to-end verified with curl: - Full flow: create → eval pay → evaluating → work pay → executing → complete - Error cases: 400 on missing body/param, 404 on unknown job
2026-03-18 15:31:26 +00:00
/jobs:
post:
operationId: createJob
tags: [jobs]
summary: Create a new agent job
description: Accepts a request, creates a job row, and issues an eval fee Lightning invoice.
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CreateJobRequest"
responses:
"201":
description: Job created successfully
content:
application/json:
schema:
$ref: "#/components/schemas/CreateJobResponse"
"400":
description: Invalid request body
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Server error
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/jobs/{id}:
get:
operationId: getJob
tags: [jobs]
summary: Get job status
description: Returns current job state. Automatically advances the state machine when a pending invoice is found to be paid.
parameters:
- name: id
in: path
required: true
schema:
type: string
responses:
"200":
description: Job status
content:
application/json:
schema:
$ref: "#/components/schemas/JobStatusResponse"
"404":
description: Job not found
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Server error
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/jobs/{id}/refund:
post:
operationId: claimRefund
tags: [jobs]
summary: Claim a refund for overpayment
description: |
After a job completes, if the actual cost (tokens used + infra + margin) was
less than the work invoice amount, the difference is owed back to the user.
Submit a BOLT11 invoice for exactly `refundAmountSats` to receive the payment.
Idempotent: returns 409 if already paid or if no refund is owed.
parameters:
- name: id
in: path
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/ClaimRefundRequest"
responses:
"200":
description: Refund sent
content:
application/json:
schema:
$ref: "#/components/schemas/ClaimRefundResponse"
"400":
description: Missing invoice, wrong amount, or invalid BOLT11
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Job not found
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"409":
description: Job not complete, refund already paid, or no refund owed
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Server error (e.g. Lightning payment failure)
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/sessions:
post:
operationId: createSession
tags: [sessions]
summary: Create a pre-funded session
description: |
Opens a new session. Pay the returned Lightning invoice to activate it.
Once active, use the `macaroon` from GET /sessions/:id to authenticate requests.
Deposits: 10010,000 sats. Sessions expire after 24 h of inactivity.
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CreateSessionRequest"
responses:
"201":
description: Session created -- awaiting deposit payment
content:
application/json:
schema:
$ref: "#/components/schemas/CreateSessionResponse"
"400":
description: Invalid amount
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Server error
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/sessions/{id}:
get:
operationId: getSession
tags: [sessions]
summary: Get session status
description: Returns current state, balance, and pending invoice info. Auto-advances on payment.
parameters:
- name: id
in: path
required: true
schema:
type: string
responses:
"200":
description: Session status
content:
application/json:
schema:
$ref: "#/components/schemas/SessionStatusResponse"
"404":
description: Session not found
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/sessions/{id}/request:
post:
operationId: submitSessionRequest
tags: [sessions]
summary: Submit a request against a session balance
description: |
Runs eval + work and debits the actual compute cost from the session balance.
Rejected requests still incur a small eval fee. Requires `Authorization: Bearer <macaroon>`.
parameters:
- name: id
in: path
required: true
schema:
type: string
security:
- sessionMacaroon: []
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/SessionRequestBody"
responses:
"200":
description: Request completed (or rejected)
content:
application/json:
schema:
$ref: "#/components/schemas/SessionRequestResponse"
"401":
description: Missing or invalid macaroon
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"402":
description: Insufficient balance
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"409":
description: Session not active
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Session expired
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/sessions/{id}/topup:
post:
operationId: topupSession
tags: [sessions]
summary: Add sats to a session
description: |
Creates a new Lightning invoice to top up the session balance.
Only one pending topup at a time. Paying it resumes a paused session.
parameters:
- name: id
in: path
required: true
schema:
type: string
security:
- sessionMacaroon: []
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CreateSessionRequest"
responses:
"200":
description: Topup invoice created
content:
application/json:
schema:
$ref: "#/components/schemas/TopupSessionResponse"
"400":
description: Invalid amount
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Invalid macaroon
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"409":
description: Session not active/paused, or topup already pending
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
Task #3: MVP API — payment-gated jobs + demo endpoint OpenAPI spec (lib/api-spec/openapi.yaml) - Added POST /jobs, GET /jobs/{id}, GET /demo endpoints - Added schemas: CreateJobRequest, CreateJobResponse, JobStatusResponse, InvoiceInfo, JobState, DemoResponse, ErrorResponse - Ran codegen: generated CreateJobBody, GetJobResponse, RunDemoQueryParams etc. Jobs router (artifacts/api-server/src/routes/jobs.ts) - POST /jobs: validates body, creates LNbits eval invoice, inserts job + invoice in a DB transaction, returns { jobId, evalInvoice } - GET /jobs/:id: fetches job, calls advanceJob() helper, returns state- appropriate payload (eval/work invoice, reason, result, errorMessage) - advanceJob() state machine: - awaiting_eval_payment: checks LNbits, atomically marks paid + advances state via optimistic WHERE state='awaiting_eval_payment'; runs AgentService.evaluateRequest, branches to awaiting_work_payment or rejected - awaiting_work_payment: same pattern for work invoice, runs AgentService.executeWork, advances to complete - Any agent/LNbits error transitions job to failed Demo router (artifacts/api-server/src/routes/demo.ts) - GET /demo?request=...: in-memory rate limiter (5 req/hour per IP) - Explicit guard for missing request param (coerce.string() workaround) - Calls AgentService.executeWork directly, returns { result } Dev router (artifacts/api-server/src/routes/dev.ts) - POST /dev/stub/pay/:paymentHash: marks stub invoice paid in-memory - Only mounted when NODE_ENV !== 'production' Route index updated to mount all three routers replit.md: documented full curl flow with all 6 steps, demo endpoint, and dev stub-pay trigger End-to-end verified with curl: - Full flow: create → eval pay → evaluating → work pay → executing → complete - Error cases: 400 on missing body/param, 404 on unknown job
2026-03-18 15:31:26 +00:00
/demo:
get:
operationId: runDemo
tags: [demo]
summary: Free demo (rate-limited)
description: Runs the agent without payment. Limited to 5 requests per IP per hour.
parameters:
- name: request
in: query
required: true
schema:
type: string
responses:
"200":
description: Demo result
headers:
X-RateLimit-Limit:
schema:
type: integer
description: Maximum requests allowed per window (always 5)
X-RateLimit-Remaining:
schema:
type: integer
description: Requests remaining in the current window
X-RateLimit-Reset:
schema:
type: integer
description: Unix epoch seconds when the rate limit window resets
Task #3: MVP API — payment-gated jobs + demo endpoint OpenAPI spec (lib/api-spec/openapi.yaml) - Added POST /jobs, GET /jobs/{id}, GET /demo endpoints - Added schemas: CreateJobRequest, CreateJobResponse, JobStatusResponse, InvoiceInfo, JobState, DemoResponse, ErrorResponse - Ran codegen: generated CreateJobBody, GetJobResponse, RunDemoQueryParams etc. Jobs router (artifacts/api-server/src/routes/jobs.ts) - POST /jobs: validates body, creates LNbits eval invoice, inserts job + invoice in a DB transaction, returns { jobId, evalInvoice } - GET /jobs/:id: fetches job, calls advanceJob() helper, returns state- appropriate payload (eval/work invoice, reason, result, errorMessage) - advanceJob() state machine: - awaiting_eval_payment: checks LNbits, atomically marks paid + advances state via optimistic WHERE state='awaiting_eval_payment'; runs AgentService.evaluateRequest, branches to awaiting_work_payment or rejected - awaiting_work_payment: same pattern for work invoice, runs AgentService.executeWork, advances to complete - Any agent/LNbits error transitions job to failed Demo router (artifacts/api-server/src/routes/demo.ts) - GET /demo?request=...: in-memory rate limiter (5 req/hour per IP) - Explicit guard for missing request param (coerce.string() workaround) - Calls AgentService.executeWork directly, returns { result } Dev router (artifacts/api-server/src/routes/dev.ts) - POST /dev/stub/pay/:paymentHash: marks stub invoice paid in-memory - Only mounted when NODE_ENV !== 'production' Route index updated to mount all three routers replit.md: documented full curl flow with all 6 steps, demo endpoint, and dev stub-pay trigger End-to-end verified with curl: - Full flow: create → eval pay → evaluating → work pay → executing → complete - Error cases: 400 on missing body/param, 404 on unknown job
2026-03-18 15:31:26 +00:00
content:
application/json:
schema:
$ref: "#/components/schemas/DemoResponse"
"400":
description: Missing or invalid request param
headers:
X-RateLimit-Limit:
schema:
type: integer
X-RateLimit-Remaining:
schema:
type: integer
X-RateLimit-Reset:
schema:
type: integer
Task #3: MVP API — payment-gated jobs + demo endpoint OpenAPI spec (lib/api-spec/openapi.yaml) - Added POST /jobs, GET /jobs/{id}, GET /demo endpoints - Added schemas: CreateJobRequest, CreateJobResponse, JobStatusResponse, InvoiceInfo, JobState, DemoResponse, ErrorResponse - Ran codegen: generated CreateJobBody, GetJobResponse, RunDemoQueryParams etc. Jobs router (artifacts/api-server/src/routes/jobs.ts) - POST /jobs: validates body, creates LNbits eval invoice, inserts job + invoice in a DB transaction, returns { jobId, evalInvoice } - GET /jobs/:id: fetches job, calls advanceJob() helper, returns state- appropriate payload (eval/work invoice, reason, result, errorMessage) - advanceJob() state machine: - awaiting_eval_payment: checks LNbits, atomically marks paid + advances state via optimistic WHERE state='awaiting_eval_payment'; runs AgentService.evaluateRequest, branches to awaiting_work_payment or rejected - awaiting_work_payment: same pattern for work invoice, runs AgentService.executeWork, advances to complete - Any agent/LNbits error transitions job to failed Demo router (artifacts/api-server/src/routes/demo.ts) - GET /demo?request=...: in-memory rate limiter (5 req/hour per IP) - Explicit guard for missing request param (coerce.string() workaround) - Calls AgentService.executeWork directly, returns { result } Dev router (artifacts/api-server/src/routes/dev.ts) - POST /dev/stub/pay/:paymentHash: marks stub invoice paid in-memory - Only mounted when NODE_ENV !== 'production' Route index updated to mount all three routers replit.md: documented full curl flow with all 6 steps, demo endpoint, and dev stub-pay trigger End-to-end verified with curl: - Full flow: create → eval pay → evaluating → work pay → executing → complete - Error cases: 400 on missing body/param, 404 on unknown job
2026-03-18 15:31:26 +00:00
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Rate limit exceeded
headers:
X-RateLimit-Limit:
schema:
type: integer
X-RateLimit-Remaining:
schema:
type: integer
description: Always 0 when rate limited
X-RateLimit-Reset:
schema:
type: integer
Task #3: MVP API — payment-gated jobs + demo endpoint OpenAPI spec (lib/api-spec/openapi.yaml) - Added POST /jobs, GET /jobs/{id}, GET /demo endpoints - Added schemas: CreateJobRequest, CreateJobResponse, JobStatusResponse, InvoiceInfo, JobState, DemoResponse, ErrorResponse - Ran codegen: generated CreateJobBody, GetJobResponse, RunDemoQueryParams etc. Jobs router (artifacts/api-server/src/routes/jobs.ts) - POST /jobs: validates body, creates LNbits eval invoice, inserts job + invoice in a DB transaction, returns { jobId, evalInvoice } - GET /jobs/:id: fetches job, calls advanceJob() helper, returns state- appropriate payload (eval/work invoice, reason, result, errorMessage) - advanceJob() state machine: - awaiting_eval_payment: checks LNbits, atomically marks paid + advances state via optimistic WHERE state='awaiting_eval_payment'; runs AgentService.evaluateRequest, branches to awaiting_work_payment or rejected - awaiting_work_payment: same pattern for work invoice, runs AgentService.executeWork, advances to complete - Any agent/LNbits error transitions job to failed Demo router (artifacts/api-server/src/routes/demo.ts) - GET /demo?request=...: in-memory rate limiter (5 req/hour per IP) - Explicit guard for missing request param (coerce.string() workaround) - Calls AgentService.executeWork directly, returns { result } Dev router (artifacts/api-server/src/routes/dev.ts) - POST /dev/stub/pay/:paymentHash: marks stub invoice paid in-memory - Only mounted when NODE_ENV !== 'production' Route index updated to mount all three routers replit.md: documented full curl flow with all 6 steps, demo endpoint, and dev stub-pay trigger End-to-end verified with curl: - Full flow: create → eval pay → evaluating → work pay → executing → complete - Error cases: 400 on missing body/param, 404 on unknown job
2026-03-18 15:31:26 +00:00
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Server error
headers:
X-RateLimit-Limit:
schema:
type: integer
X-RateLimit-Remaining:
schema:
type: integer
X-RateLimit-Reset:
schema:
type: integer
Task #3: MVP API — payment-gated jobs + demo endpoint OpenAPI spec (lib/api-spec/openapi.yaml) - Added POST /jobs, GET /jobs/{id}, GET /demo endpoints - Added schemas: CreateJobRequest, CreateJobResponse, JobStatusResponse, InvoiceInfo, JobState, DemoResponse, ErrorResponse - Ran codegen: generated CreateJobBody, GetJobResponse, RunDemoQueryParams etc. Jobs router (artifacts/api-server/src/routes/jobs.ts) - POST /jobs: validates body, creates LNbits eval invoice, inserts job + invoice in a DB transaction, returns { jobId, evalInvoice } - GET /jobs/:id: fetches job, calls advanceJob() helper, returns state- appropriate payload (eval/work invoice, reason, result, errorMessage) - advanceJob() state machine: - awaiting_eval_payment: checks LNbits, atomically marks paid + advances state via optimistic WHERE state='awaiting_eval_payment'; runs AgentService.evaluateRequest, branches to awaiting_work_payment or rejected - awaiting_work_payment: same pattern for work invoice, runs AgentService.executeWork, advances to complete - Any agent/LNbits error transitions job to failed Demo router (artifacts/api-server/src/routes/demo.ts) - GET /demo?request=...: in-memory rate limiter (5 req/hour per IP) - Explicit guard for missing request param (coerce.string() workaround) - Calls AgentService.executeWork directly, returns { result } Dev router (artifacts/api-server/src/routes/dev.ts) - POST /dev/stub/pay/:paymentHash: marks stub invoice paid in-memory - Only mounted when NODE_ENV !== 'production' Route index updated to mount all three routers replit.md: documented full curl flow with all 6 steps, demo endpoint, and dev stub-pay trigger End-to-end verified with curl: - Full flow: create → eval pay → evaluating → work pay → executing → complete - Error cases: 400 on missing body/param, 404 on unknown job
2026-03-18 15:31:26 +00:00
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/gemini/conversations:
get:
operationId: listGeminiConversations
tags: [gemini]
summary: List all conversations
responses:
"200":
description: List of conversations
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/GeminiConversation"
post:
operationId: createGeminiConversation
tags: [gemini]
summary: Create a new conversation
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CreateGeminiConversationBody"
responses:
"201":
description: Created conversation
content:
application/json:
schema:
$ref: "#/components/schemas/GeminiConversation"
/gemini/conversations/{id}:
get:
operationId: getGeminiConversation
tags: [gemini]
summary: Get conversation with messages
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
"200":
description: Conversation with messages
content:
application/json:
schema:
$ref: "#/components/schemas/GeminiConversationWithMessages"
"404":
description: Not found
content:
application/json:
schema:
$ref: "#/components/schemas/GeminiError"
delete:
operationId: deleteGeminiConversation
tags: [gemini]
summary: Delete a conversation
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
"204":
description: Deleted
"404":
description: Not found
content:
application/json:
schema:
$ref: "#/components/schemas/GeminiError"
/gemini/conversations/{id}/messages:
get:
operationId: listGeminiMessages
tags: [gemini]
summary: List messages in a conversation
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
"200":
description: List of messages
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/GeminiMessage"
post:
operationId: sendGeminiMessage
tags: [gemini]
summary: Send a message and receive an AI response (SSE stream)
parameters:
- name: id
in: path
required: true
schema:
type: integer
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/SendGeminiMessageBody"
responses:
"200":
description: SSE stream of assistant response chunks
content:
text/event-stream: {}
/gemini/generate-image:
post:
operationId: generateGeminiImage
tags: [gemini]
summary: Generate an image from a text prompt
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/GenerateGeminiImageBody"
responses:
"200":
description: Generated image
content:
application/json:
schema:
$ref: "#/components/schemas/GenerateGeminiImageResponse"
2026-03-13 23:21:55 +00:00
components:
schemas:
HealthStatus:
type: object
properties:
status:
type: string
required:
- status
Task #3: MVP API — payment-gated jobs + demo endpoint OpenAPI spec (lib/api-spec/openapi.yaml) - Added POST /jobs, GET /jobs/{id}, GET /demo endpoints - Added schemas: CreateJobRequest, CreateJobResponse, JobStatusResponse, InvoiceInfo, JobState, DemoResponse, ErrorResponse - Ran codegen: generated CreateJobBody, GetJobResponse, RunDemoQueryParams etc. Jobs router (artifacts/api-server/src/routes/jobs.ts) - POST /jobs: validates body, creates LNbits eval invoice, inserts job + invoice in a DB transaction, returns { jobId, evalInvoice } - GET /jobs/:id: fetches job, calls advanceJob() helper, returns state- appropriate payload (eval/work invoice, reason, result, errorMessage) - advanceJob() state machine: - awaiting_eval_payment: checks LNbits, atomically marks paid + advances state via optimistic WHERE state='awaiting_eval_payment'; runs AgentService.evaluateRequest, branches to awaiting_work_payment or rejected - awaiting_work_payment: same pattern for work invoice, runs AgentService.executeWork, advances to complete - Any agent/LNbits error transitions job to failed Demo router (artifacts/api-server/src/routes/demo.ts) - GET /demo?request=...: in-memory rate limiter (5 req/hour per IP) - Explicit guard for missing request param (coerce.string() workaround) - Calls AgentService.executeWork directly, returns { result } Dev router (artifacts/api-server/src/routes/dev.ts) - POST /dev/stub/pay/:paymentHash: marks stub invoice paid in-memory - Only mounted when NODE_ENV !== 'production' Route index updated to mount all three routers replit.md: documented full curl flow with all 6 steps, demo endpoint, and dev stub-pay trigger End-to-end verified with curl: - Full flow: create → eval pay → evaluating → work pay → executing → complete - Error cases: 400 on missing body/param, 404 on unknown job
2026-03-18 15:31:26 +00:00
ErrorResponse:
type: object
required:
- error
properties:
error:
type: string
InvoiceInfo:
type: object
required:
- paymentRequest
- amountSats
properties:
paymentRequest:
type: string
amountSats:
type: integer
CreateJobRequest:
type: object
required:
- request
properties:
request:
type: string
minLength: 1
CreateJobResponse:
type: object
required:
- jobId
- createdAt
Task #3: MVP API — payment-gated jobs + demo endpoint OpenAPI spec (lib/api-spec/openapi.yaml) - Added POST /jobs, GET /jobs/{id}, GET /demo endpoints - Added schemas: CreateJobRequest, CreateJobResponse, JobStatusResponse, InvoiceInfo, JobState, DemoResponse, ErrorResponse - Ran codegen: generated CreateJobBody, GetJobResponse, RunDemoQueryParams etc. Jobs router (artifacts/api-server/src/routes/jobs.ts) - POST /jobs: validates body, creates LNbits eval invoice, inserts job + invoice in a DB transaction, returns { jobId, evalInvoice } - GET /jobs/:id: fetches job, calls advanceJob() helper, returns state- appropriate payload (eval/work invoice, reason, result, errorMessage) - advanceJob() state machine: - awaiting_eval_payment: checks LNbits, atomically marks paid + advances state via optimistic WHERE state='awaiting_eval_payment'; runs AgentService.evaluateRequest, branches to awaiting_work_payment or rejected - awaiting_work_payment: same pattern for work invoice, runs AgentService.executeWork, advances to complete - Any agent/LNbits error transitions job to failed Demo router (artifacts/api-server/src/routes/demo.ts) - GET /demo?request=...: in-memory rate limiter (5 req/hour per IP) - Explicit guard for missing request param (coerce.string() workaround) - Calls AgentService.executeWork directly, returns { result } Dev router (artifacts/api-server/src/routes/dev.ts) - POST /dev/stub/pay/:paymentHash: marks stub invoice paid in-memory - Only mounted when NODE_ENV !== 'production' Route index updated to mount all three routers replit.md: documented full curl flow with all 6 steps, demo endpoint, and dev stub-pay trigger End-to-end verified with curl: - Full flow: create → eval pay → evaluating → work pay → executing → complete - Error cases: 400 on missing body/param, 404 on unknown job
2026-03-18 15:31:26 +00:00
- evalInvoice
properties:
jobId:
type: string
createdAt:
type: string
format: date-time
description: ISO 8601 timestamp of job creation
Task #3: MVP API — payment-gated jobs + demo endpoint OpenAPI spec (lib/api-spec/openapi.yaml) - Added POST /jobs, GET /jobs/{id}, GET /demo endpoints - Added schemas: CreateJobRequest, CreateJobResponse, JobStatusResponse, InvoiceInfo, JobState, DemoResponse, ErrorResponse - Ran codegen: generated CreateJobBody, GetJobResponse, RunDemoQueryParams etc. Jobs router (artifacts/api-server/src/routes/jobs.ts) - POST /jobs: validates body, creates LNbits eval invoice, inserts job + invoice in a DB transaction, returns { jobId, evalInvoice } - GET /jobs/:id: fetches job, calls advanceJob() helper, returns state- appropriate payload (eval/work invoice, reason, result, errorMessage) - advanceJob() state machine: - awaiting_eval_payment: checks LNbits, atomically marks paid + advances state via optimistic WHERE state='awaiting_eval_payment'; runs AgentService.evaluateRequest, branches to awaiting_work_payment or rejected - awaiting_work_payment: same pattern for work invoice, runs AgentService.executeWork, advances to complete - Any agent/LNbits error transitions job to failed Demo router (artifacts/api-server/src/routes/demo.ts) - GET /demo?request=...: in-memory rate limiter (5 req/hour per IP) - Explicit guard for missing request param (coerce.string() workaround) - Calls AgentService.executeWork directly, returns { result } Dev router (artifacts/api-server/src/routes/dev.ts) - POST /dev/stub/pay/:paymentHash: marks stub invoice paid in-memory - Only mounted when NODE_ENV !== 'production' Route index updated to mount all three routers replit.md: documented full curl flow with all 6 steps, demo endpoint, and dev stub-pay trigger End-to-end verified with curl: - Full flow: create → eval pay → evaluating → work pay → executing → complete - Error cases: 400 on missing body/param, 404 on unknown job
2026-03-18 15:31:26 +00:00
evalInvoice:
$ref: "#/components/schemas/InvoiceInfo"
JobState:
type: string
enum:
- awaiting_eval_payment
- evaluating
- rejected
- awaiting_work_payment
- executing
- complete
- failed
PricingBreakdown:
type: object
description: Cost breakdown shown with the work invoice (estimations at invoice-creation time)
properties:
estimatedCostUsd:
type: number
description: Total estimated cost in USD (token cost + DO infra + margin)
marginPct:
type: number
description: Originator margin percentage applied
btcPriceUsd:
type: number
description: BTC/USD spot price used to convert the invoice to sats
CostLedger:
type: object
description: Honest post-work accounting stored after the job completes
properties:
actualInputTokens:
type: integer
actualOutputTokens:
type: integer
Task #6: Cost-based work fee pricing with BTC oracle ## New files - btc-oracle.ts: CoinGecko BTC/USD fetch (60s cache), usdToSats() helper (ceil, min 1 sat), 5s abort timeout, fallback to BTC_PRICE_USD_FALLBACK env var (default $100k) - lib/db/migrations/0002_cost_based_pricing.sql: SQL migration artifact adding 6 new columns to jobs table (estimated_cost_usd, margin_pct, btc_price_usd, actual_input_tokens, actual_output_tokens, actual_cost_usd); idempotent via ADD COLUMN IF NOT EXISTS ## Modified files - pricing.ts: Full rewrite — per-model token rates (Haiku/Sonnet, env-var overridable), DO infra amortisation per request, originator margin %, estimateInputTokens/Output by tier, calculateActualCostUsd() for post-work ledger, async calculateWorkFeeSats() → WorkFeeBreakdown - agent.ts: WorkResult now includes inputTokens + outputTokens from Anthropic usage; workModel/evalModel exposed as readonly public; EVAL_MODEL/WORK_MODEL env var support - lib/db/src/schema/jobs.ts: 6 new real/integer columns; schema pushed to DB - jobs.ts route: Work invoice creation calls pricingService.calculateWorkFeeSats() async; stores estimatedCostUsd/marginPct/btcPriceUsd; post-work stores actualInputTokens/ actualOutputTokens/actualCostUsd; GET response includes pricingBreakdown and costLedger with totalTokens (input + output computed field) - openapi.yaml: PricingBreakdown + CostLedger schemas (with totalTokens) added - lib/api-zod/src/generated/api.ts: Regenerated with new schemas - lib/api-client-react/src/generated/api.schemas.ts: Regenerated (PricingBreakdown, CostLedger) - replit.md: 17 new env vars documented in cost-based pricing section
2026-03-18 19:25:06 +00:00
totalTokens:
type: integer
description: Sum of actualInputTokens + actualOutputTokens
actualCostUsd:
type: number
description: Raw Anthropic token cost (no infra, no margin)
actualChargeUsd:
type: number
description: What we honestly charged in USD (actual token cost + DO infra + margin)
estimatedCostUsd:
type: number
description: Original estimate used to create the work invoice
actualAmountSats:
type: integer
description: Honest sats charge (actual cost converted at the locked BTC price)
workAmountSats:
type: integer
description: Amount the user originally paid in sats
refundAmountSats:
type: integer
description: Sats owed back to the user (workAmountSats - actualAmountSats, >= 0)
refundState:
type: string
enum: [not_applicable, pending, paid]
description: Lifecycle of the refund for this job
marginPct:
type: number
btcPriceUsd:
type: number
description: BTC/USD price locked at invoice creation time
Task #3: MVP API — payment-gated jobs + demo endpoint OpenAPI spec (lib/api-spec/openapi.yaml) - Added POST /jobs, GET /jobs/{id}, GET /demo endpoints - Added schemas: CreateJobRequest, CreateJobResponse, JobStatusResponse, InvoiceInfo, JobState, DemoResponse, ErrorResponse - Ran codegen: generated CreateJobBody, GetJobResponse, RunDemoQueryParams etc. Jobs router (artifacts/api-server/src/routes/jobs.ts) - POST /jobs: validates body, creates LNbits eval invoice, inserts job + invoice in a DB transaction, returns { jobId, evalInvoice } - GET /jobs/:id: fetches job, calls advanceJob() helper, returns state- appropriate payload (eval/work invoice, reason, result, errorMessage) - advanceJob() state machine: - awaiting_eval_payment: checks LNbits, atomically marks paid + advances state via optimistic WHERE state='awaiting_eval_payment'; runs AgentService.evaluateRequest, branches to awaiting_work_payment or rejected - awaiting_work_payment: same pattern for work invoice, runs AgentService.executeWork, advances to complete - Any agent/LNbits error transitions job to failed Demo router (artifacts/api-server/src/routes/demo.ts) - GET /demo?request=...: in-memory rate limiter (5 req/hour per IP) - Explicit guard for missing request param (coerce.string() workaround) - Calls AgentService.executeWork directly, returns { result } Dev router (artifacts/api-server/src/routes/dev.ts) - POST /dev/stub/pay/:paymentHash: marks stub invoice paid in-memory - Only mounted when NODE_ENV !== 'production' Route index updated to mount all three routers replit.md: documented full curl flow with all 6 steps, demo endpoint, and dev stub-pay trigger End-to-end verified with curl: - Full flow: create → eval pay → evaluating → work pay → executing → complete - Error cases: 400 on missing body/param, 404 on unknown job
2026-03-18 15:31:26 +00:00
JobStatusResponse:
type: object
required:
- jobId
- state
- createdAt
Task #3: MVP API — payment-gated jobs + demo endpoint OpenAPI spec (lib/api-spec/openapi.yaml) - Added POST /jobs, GET /jobs/{id}, GET /demo endpoints - Added schemas: CreateJobRequest, CreateJobResponse, JobStatusResponse, InvoiceInfo, JobState, DemoResponse, ErrorResponse - Ran codegen: generated CreateJobBody, GetJobResponse, RunDemoQueryParams etc. Jobs router (artifacts/api-server/src/routes/jobs.ts) - POST /jobs: validates body, creates LNbits eval invoice, inserts job + invoice in a DB transaction, returns { jobId, evalInvoice } - GET /jobs/:id: fetches job, calls advanceJob() helper, returns state- appropriate payload (eval/work invoice, reason, result, errorMessage) - advanceJob() state machine: - awaiting_eval_payment: checks LNbits, atomically marks paid + advances state via optimistic WHERE state='awaiting_eval_payment'; runs AgentService.evaluateRequest, branches to awaiting_work_payment or rejected - awaiting_work_payment: same pattern for work invoice, runs AgentService.executeWork, advances to complete - Any agent/LNbits error transitions job to failed Demo router (artifacts/api-server/src/routes/demo.ts) - GET /demo?request=...: in-memory rate limiter (5 req/hour per IP) - Explicit guard for missing request param (coerce.string() workaround) - Calls AgentService.executeWork directly, returns { result } Dev router (artifacts/api-server/src/routes/dev.ts) - POST /dev/stub/pay/:paymentHash: marks stub invoice paid in-memory - Only mounted when NODE_ENV !== 'production' Route index updated to mount all three routers replit.md: documented full curl flow with all 6 steps, demo endpoint, and dev stub-pay trigger End-to-end verified with curl: - Full flow: create → eval pay → evaluating → work pay → executing → complete - Error cases: 400 on missing body/param, 404 on unknown job
2026-03-18 15:31:26 +00:00
properties:
jobId:
type: string
state:
$ref: "#/components/schemas/JobState"
createdAt:
type: string
format: date-time
description: ISO 8601 timestamp of job creation (always present)
completedAt:
type: string
format: date-time
nullable: true
description: ISO 8601 timestamp of job completion; null when not yet complete
Task #3: MVP API — payment-gated jobs + demo endpoint OpenAPI spec (lib/api-spec/openapi.yaml) - Added POST /jobs, GET /jobs/{id}, GET /demo endpoints - Added schemas: CreateJobRequest, CreateJobResponse, JobStatusResponse, InvoiceInfo, JobState, DemoResponse, ErrorResponse - Ran codegen: generated CreateJobBody, GetJobResponse, RunDemoQueryParams etc. Jobs router (artifacts/api-server/src/routes/jobs.ts) - POST /jobs: validates body, creates LNbits eval invoice, inserts job + invoice in a DB transaction, returns { jobId, evalInvoice } - GET /jobs/:id: fetches job, calls advanceJob() helper, returns state- appropriate payload (eval/work invoice, reason, result, errorMessage) - advanceJob() state machine: - awaiting_eval_payment: checks LNbits, atomically marks paid + advances state via optimistic WHERE state='awaiting_eval_payment'; runs AgentService.evaluateRequest, branches to awaiting_work_payment or rejected - awaiting_work_payment: same pattern for work invoice, runs AgentService.executeWork, advances to complete - Any agent/LNbits error transitions job to failed Demo router (artifacts/api-server/src/routes/demo.ts) - GET /demo?request=...: in-memory rate limiter (5 req/hour per IP) - Explicit guard for missing request param (coerce.string() workaround) - Calls AgentService.executeWork directly, returns { result } Dev router (artifacts/api-server/src/routes/dev.ts) - POST /dev/stub/pay/:paymentHash: marks stub invoice paid in-memory - Only mounted when NODE_ENV !== 'production' Route index updated to mount all three routers replit.md: documented full curl flow with all 6 steps, demo endpoint, and dev stub-pay trigger End-to-end verified with curl: - Full flow: create → eval pay → evaluating → work pay → executing → complete - Error cases: 400 on missing body/param, 404 on unknown job
2026-03-18 15:31:26 +00:00
evalInvoice:
$ref: "#/components/schemas/InvoiceInfo"
workInvoice:
$ref: "#/components/schemas/InvoiceInfo"
pricingBreakdown:
$ref: "#/components/schemas/PricingBreakdown"
Task #3: MVP API — payment-gated jobs + demo endpoint OpenAPI spec (lib/api-spec/openapi.yaml) - Added POST /jobs, GET /jobs/{id}, GET /demo endpoints - Added schemas: CreateJobRequest, CreateJobResponse, JobStatusResponse, InvoiceInfo, JobState, DemoResponse, ErrorResponse - Ran codegen: generated CreateJobBody, GetJobResponse, RunDemoQueryParams etc. Jobs router (artifacts/api-server/src/routes/jobs.ts) - POST /jobs: validates body, creates LNbits eval invoice, inserts job + invoice in a DB transaction, returns { jobId, evalInvoice } - GET /jobs/:id: fetches job, calls advanceJob() helper, returns state- appropriate payload (eval/work invoice, reason, result, errorMessage) - advanceJob() state machine: - awaiting_eval_payment: checks LNbits, atomically marks paid + advances state via optimistic WHERE state='awaiting_eval_payment'; runs AgentService.evaluateRequest, branches to awaiting_work_payment or rejected - awaiting_work_payment: same pattern for work invoice, runs AgentService.executeWork, advances to complete - Any agent/LNbits error transitions job to failed Demo router (artifacts/api-server/src/routes/demo.ts) - GET /demo?request=...: in-memory rate limiter (5 req/hour per IP) - Explicit guard for missing request param (coerce.string() workaround) - Calls AgentService.executeWork directly, returns { result } Dev router (artifacts/api-server/src/routes/dev.ts) - POST /dev/stub/pay/:paymentHash: marks stub invoice paid in-memory - Only mounted when NODE_ENV !== 'production' Route index updated to mount all three routers replit.md: documented full curl flow with all 6 steps, demo endpoint, and dev stub-pay trigger End-to-end verified with curl: - Full flow: create → eval pay → evaluating → work pay → executing → complete - Error cases: 400 on missing body/param, 404 on unknown job
2026-03-18 15:31:26 +00:00
reason:
type: string
result:
type: string
costLedger:
$ref: "#/components/schemas/CostLedger"
Task #3: MVP API — payment-gated jobs + demo endpoint OpenAPI spec (lib/api-spec/openapi.yaml) - Added POST /jobs, GET /jobs/{id}, GET /demo endpoints - Added schemas: CreateJobRequest, CreateJobResponse, JobStatusResponse, InvoiceInfo, JobState, DemoResponse, ErrorResponse - Ran codegen: generated CreateJobBody, GetJobResponse, RunDemoQueryParams etc. Jobs router (artifacts/api-server/src/routes/jobs.ts) - POST /jobs: validates body, creates LNbits eval invoice, inserts job + invoice in a DB transaction, returns { jobId, evalInvoice } - GET /jobs/:id: fetches job, calls advanceJob() helper, returns state- appropriate payload (eval/work invoice, reason, result, errorMessage) - advanceJob() state machine: - awaiting_eval_payment: checks LNbits, atomically marks paid + advances state via optimistic WHERE state='awaiting_eval_payment'; runs AgentService.evaluateRequest, branches to awaiting_work_payment or rejected - awaiting_work_payment: same pattern for work invoice, runs AgentService.executeWork, advances to complete - Any agent/LNbits error transitions job to failed Demo router (artifacts/api-server/src/routes/demo.ts) - GET /demo?request=...: in-memory rate limiter (5 req/hour per IP) - Explicit guard for missing request param (coerce.string() workaround) - Calls AgentService.executeWork directly, returns { result } Dev router (artifacts/api-server/src/routes/dev.ts) - POST /dev/stub/pay/:paymentHash: marks stub invoice paid in-memory - Only mounted when NODE_ENV !== 'production' Route index updated to mount all three routers replit.md: documented full curl flow with all 6 steps, demo endpoint, and dev stub-pay trigger End-to-end verified with curl: - Full flow: create → eval pay → evaluating → work pay → executing → complete - Error cases: 400 on missing body/param, 404 on unknown job
2026-03-18 15:31:26 +00:00
errorMessage:
type: string
SessionState:
type: string
enum: [awaiting_payment, active, paused, expired]
SessionInvoiceInfo:
type: object
properties:
paymentRequest:
type: string
amountSats:
type: integer
paymentHash:
type: string
description: Only present in stub/dev mode
CreateSessionRequest:
type: object
required: [amount_sats]
properties:
amount_sats:
type: integer
description: Deposit amount (10010,000 sats)
minimum: 100
maximum: 10000
CreateSessionResponse:
type: object
required: [sessionId, state, invoice]
properties:
sessionId:
type: string
state:
$ref: "#/components/schemas/SessionState"
invoice:
$ref: "#/components/schemas/SessionInvoiceInfo"
SessionStatusResponse:
type: object
required: [sessionId, state, balanceSats]
properties:
sessionId:
type: string
state:
$ref: "#/components/schemas/SessionState"
balanceSats:
type: integer
minimumBalanceSats:
type: integer
macaroon:
type: string
description: Bearer token for authenticating requests; present when active or paused
expiresAt:
type: string
format: date-time
invoice:
$ref: "#/components/schemas/SessionInvoiceInfo"
description: Present when state is awaiting_payment
pendingTopup:
$ref: "#/components/schemas/SessionInvoiceInfo"
description: Present when a topup invoice is outstanding
SessionRequestBody:
type: object
required: [request]
properties:
request:
type: string
minLength: 1
SessionCostBreakdown:
type: object
properties:
evalSats:
type: integer
workSats:
type: integer
totalSats:
type: integer
btcPriceUsd:
type: number
SessionRequestResponse:
type: object
required: [requestId, state, debitedSats, balanceRemaining]
properties:
requestId:
type: string
state:
type: string
enum: [complete, rejected, failed]
result:
type: string
reason:
type: string
errorMessage:
type: string
debitedSats:
type: integer
balanceRemaining:
type: integer
cost:
$ref: "#/components/schemas/SessionCostBreakdown"
TopupSessionResponse:
type: object
required: [sessionId, topup]
properties:
sessionId:
type: string
topup:
$ref: "#/components/schemas/SessionInvoiceInfo"
ClaimRefundRequest:
type: object
required:
- invoice
properties:
invoice:
type: string
description: BOLT11 invoice for exactly refundAmountSats
ClaimRefundResponse:
type: object
required:
- ok
- refundAmountSats
- paymentHash
- message
properties:
ok:
type: boolean
refundAmountSats:
type: integer
paymentHash:
type: string
message:
type: string
Task #3: MVP API — payment-gated jobs + demo endpoint OpenAPI spec (lib/api-spec/openapi.yaml) - Added POST /jobs, GET /jobs/{id}, GET /demo endpoints - Added schemas: CreateJobRequest, CreateJobResponse, JobStatusResponse, InvoiceInfo, JobState, DemoResponse, ErrorResponse - Ran codegen: generated CreateJobBody, GetJobResponse, RunDemoQueryParams etc. Jobs router (artifacts/api-server/src/routes/jobs.ts) - POST /jobs: validates body, creates LNbits eval invoice, inserts job + invoice in a DB transaction, returns { jobId, evalInvoice } - GET /jobs/:id: fetches job, calls advanceJob() helper, returns state- appropriate payload (eval/work invoice, reason, result, errorMessage) - advanceJob() state machine: - awaiting_eval_payment: checks LNbits, atomically marks paid + advances state via optimistic WHERE state='awaiting_eval_payment'; runs AgentService.evaluateRequest, branches to awaiting_work_payment or rejected - awaiting_work_payment: same pattern for work invoice, runs AgentService.executeWork, advances to complete - Any agent/LNbits error transitions job to failed Demo router (artifacts/api-server/src/routes/demo.ts) - GET /demo?request=...: in-memory rate limiter (5 req/hour per IP) - Explicit guard for missing request param (coerce.string() workaround) - Calls AgentService.executeWork directly, returns { result } Dev router (artifacts/api-server/src/routes/dev.ts) - POST /dev/stub/pay/:paymentHash: marks stub invoice paid in-memory - Only mounted when NODE_ENV !== 'production' Route index updated to mount all three routers replit.md: documented full curl flow with all 6 steps, demo endpoint, and dev stub-pay trigger End-to-end verified with curl: - Full flow: create → eval pay → evaluating → work pay → executing → complete - Error cases: 400 on missing body/param, 404 on unknown job
2026-03-18 15:31:26 +00:00
DemoResponse:
type: object
required:
- result
properties:
result:
type: string
GeminiConversation:
type: object
required: [id, title, createdAt]
properties:
id:
type: integer
title:
type: string
createdAt:
type: string
format: date-time
GeminiMessage:
type: object
required: [id, conversationId, role, content, createdAt]
properties:
id:
type: integer
conversationId:
type: integer
role:
type: string
content:
type: string
createdAt:
type: string
format: date-time
GeminiConversationWithMessages:
type: object
required: [id, title, createdAt, messages]
properties:
id:
type: integer
title:
type: string
createdAt:
type: string
format: date-time
messages:
type: array
items:
$ref: "#/components/schemas/GeminiMessage"
CreateGeminiConversationBody:
type: object
required: [title]
properties:
title:
type: string
SendGeminiMessageBody:
type: object
required: [content]
properties:
content:
type: string
model:
type: string
description: "Gemini model override (default: gemini-3-flash-preview)"
GenerateGeminiImageBody:
type: object
required: [prompt]
properties:
prompt:
type: string
GenerateGeminiImageResponse:
type: object
required: [b64_json, mimeType]
properties:
b64_json:
type: string
mimeType:
type: string
GeminiError:
type: object
required: [error]
properties:
error:
type: string
securitySchemes:
sessionMacaroon:
type: http
scheme: bearer
description: "Session macaroon issued when a session activates. Pass as `Authorization: Bearer <macaroon>`."