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 - 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) - name: demo description: Free demo endpoint (rate-limited) 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" /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: 100–10,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 `. 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" /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 content: application/json: schema: $ref: "#/components/schemas/DemoResponse" "400": description: Missing or invalid request param content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "429": description: Rate limit exceeded content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Server error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" components: schemas: HealthStatus: type: object properties: status: type: string required: - status 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 - evalInvoice properties: jobId: type: string 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 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 JobStatusResponse: type: object required: - jobId - state properties: jobId: type: string state: $ref: "#/components/schemas/JobState" evalInvoice: $ref: "#/components/schemas/InvoiceInfo" workInvoice: $ref: "#/components/schemas/InvoiceInfo" pricingBreakdown: $ref: "#/components/schemas/PricingBreakdown" reason: type: string result: type: string costLedger: $ref: "#/components/schemas/CostLedger" 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 (100–10,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 DemoResponse: type: object required: - result properties: result: type: string securitySchemes: sessionMacaroon: type: http scheme: bearer description: Session macaroon issued when a session activates. Pass as `Authorization: Bearer `.