This repository has been archived on 2026-03-24. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
token-gated-economy/lib/api-spec/openapi.yaml

671 lines
19 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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: 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"
/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
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
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
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
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
- createdAt
- evalInvoice
properties:
jobId:
type: string
createdAt:
type: string
format: date-time
description: ISO 8601 timestamp of job creation
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
- createdAt
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
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 (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
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 <macaroon>`.