Add Swagger docs at /docs and /openapi.json with split OpenAPI spec

Made-with: Cursor
This commit is contained in:
Michaël
2026-02-28 21:14:27 -03:00
parent bdb4892014
commit 0a6d86c8e8
21 changed files with 679 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
QuoteResult:
type: object
properties:
quote_id:
type: string
payout_sats:
type: integer
expires_at:
type: integer
ConfirmResult:
type: object
properties:
success:
type: boolean
already_consumed:
type: boolean
payout_sats:
type: integer
next_eligible_at:
type: integer
message:
type: string
payment_hash:
type: string

View File

@@ -0,0 +1,12 @@
ApiError:
type: object
required: [code, message]
properties:
code:
type: string
message:
type: string
details:
type: string
next_eligible_at:
type: integer

View File

@@ -0,0 +1,64 @@
FaucetConfig:
type: object
properties:
faucetEnabled:
type: boolean
emergencyStop:
type: boolean
cooldownDays:
type: integer
minAccountAgeDays:
type: integer
minActivityScore:
type: integer
faucetMinSats:
type: integer
faucetMaxSats:
type: integer
Stats:
type: object
properties:
balanceSats:
type: integer
totalPaidSats:
type: integer
totalClaims:
type: integer
claimsLast24h:
type: integer
dailyBudgetSats:
type: integer
spentTodaySats:
type: integer
recentPayouts:
type: array
items:
type: object
properties:
pubkey_prefix:
type: string
payout_sats:
type: integer
claimed_at:
type: integer
recentDeposits:
type: array
items:
type: object
properties:
amount_sats:
type: integer
source:
type: string
enum: [lightning, cashu]
created_at:
type: integer
DepositInfo:
type: object
properties:
lightningAddress:
type: string
nullable: true
lnurlp:
type: string
nullable: true

View File

@@ -0,0 +1,9 @@
UserProfile:
type: object
properties:
lightning_address:
type: string
nullable: true
name:
type: string
nullable: true

View File

@@ -0,0 +1,9 @@
NIP98:
type: http
scheme: bearer
bearerFormat: Nostr
description: NIP-98 HTTP Auth (Authorization Nostr <base64(json)>)
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT

View File

@@ -0,0 +1,60 @@
openapi: 3.0.3
info:
title: LNFaucet API
description: |
Lightning Network faucet: request small amounts of sats for testing.
Auth via NIP-98 (Nostr) or npub-only (limited).
version: 1.0.0
servers:
- url: http://localhost:3001
description: Local development
tags:
- name: Public
description: No authentication required
- name: Auth
description: NIP-98 or npub login
- name: Claim
description: Request sats (rate limited)
- name: User
description: Profile and refresh
paths:
/health:
$ref: './path-items/health.yaml'
/config:
$ref: './path-items/config.yaml'
/stats:
$ref: './path-items/stats.yaml'
/deposit:
$ref: './path-items/deposit.yaml'
/deposit/redeem-cashu:
$ref: './path-items/deposit-redeem-cashu.yaml'
/auth/login:
$ref: './path-items/auth-login.yaml'
/auth/login-npub:
$ref: './path-items/auth-login-npub.yaml'
/auth/me:
$ref: './path-items/auth-me.yaml'
/claim/quote:
$ref: './path-items/claim-quote.yaml'
/claim/confirm:
$ref: './path-items/claim-confirm.yaml'
/user/refresh-profile:
$ref: './path-items/user-refresh-profile.yaml'
components:
securitySchemes:
$ref: './components/security.yaml'
schemas:
FaucetConfig:
$ref: './components/schemas/faucet.yaml#/FaucetConfig'
Stats:
$ref: './components/schemas/faucet.yaml#/Stats'
DepositInfo:
$ref: './components/schemas/faucet.yaml#/DepositInfo'
QuoteResult:
$ref: './components/schemas/claim.yaml#/QuoteResult'
ConfirmResult:
$ref: './components/schemas/claim.yaml#/ConfirmResult'
UserProfile:
$ref: './components/schemas/user.yaml#/UserProfile'
ApiError:
$ref: './components/schemas/common.yaml#/ApiError'

View File

@@ -0,0 +1,33 @@
post:
tags: [Auth]
summary: Sign in with npub only (limited)
requestBody:
content:
application/json:
schema:
type: object
required: [npub]
properties:
npub:
type: string
responses:
"200":
description: Token and pubkey
content:
application/json:
schema:
type: object
properties:
token:
type: string
pubkey:
type: string
method:
type: string
example: npub
"400":
description: Invalid npub
content:
application/json:
schema:
$ref: "../components/schemas/common.yaml#/ApiError"

View File

@@ -0,0 +1,20 @@
post:
tags: [Auth]
summary: Sign in with NIP-98 (returns JWT)
security:
- NIP98: []
responses:
"200":
description: Token and pubkey
content:
application/json:
schema:
type: object
properties:
token:
type: string
pubkey:
type: string
method:
type: string
example: nip98

View File

@@ -0,0 +1,23 @@
get:
tags: [Auth]
summary: Current user from Bearer token
security:
- BearerAuth: []
responses:
"200":
description: Pubkey and method
content:
application/json:
schema:
type: object
properties:
pubkey:
type: string
method:
type: string
"401":
description: Unauthorized or invalid token
content:
application/json:
schema:
$ref: "../components/schemas/common.yaml#/ApiError"

View File

@@ -0,0 +1,39 @@
post:
tags: [Claim]
summary: Confirm quote and pay (rate limited)
security:
- BearerAuth: []
requestBody:
content:
application/json:
schema:
type: object
required: [quote_id]
properties:
quote_id:
type: string
responses:
"200":
description: Success or already consumed
content:
application/json:
schema:
$ref: "../components/schemas/claim.yaml#/ConfirmResult"
"400":
description: Invalid request
content:
application/json:
schema:
$ref: "../components/schemas/common.yaml#/ApiError"
"404":
description: Quote not found or expired
content:
application/json:
schema:
$ref: "../components/schemas/common.yaml#/ApiError"
"502":
description: Lightning payment failed
content:
application/json:
schema:
$ref: "../components/schemas/common.yaml#/ApiError"

View File

@@ -0,0 +1,28 @@
post:
tags: [Claim]
summary: Create claim quote (rate limited)
security:
- BearerAuth: []
requestBody:
content:
application/json:
schema:
type: object
required: [lightning_address]
properties:
lightning_address:
type: string
description: user@domain.tld
responses:
"200":
description: Quote
content:
application/json:
schema:
$ref: "../components/schemas/claim.yaml#/QuoteResult"
"403":
description: Not eligible or budget exceeded
content:
application/json:
schema:
$ref: "../components/schemas/common.yaml#/ApiError"

View File

@@ -0,0 +1,10 @@
get:
tags: [Public]
summary: Public faucet config
responses:
"200":
description: Faucet configuration
content:
application/json:
schema:
$ref: "../components/schemas/faucet.yaml#/FaucetConfig"

View File

@@ -0,0 +1,48 @@
post:
tags: [Public]
summary: Redeem Cashu token
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [token]
properties:
token:
type: string
description: Cashu token (cashuA... or cashuB...)
responses:
"200":
description: Redeem result
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
paid:
type: boolean
amount:
type: integer
invoiceAmount:
type: integer
netAmount:
type: integer
to:
type: string
message:
type: string
"400":
description: Invalid token or address
content:
application/json:
schema:
$ref: "../components/schemas/common.yaml#/ApiError"
"502":
description: Redeem failed
content:
application/json:
schema:
$ref: "../components/schemas/common.yaml#/ApiError"

View File

@@ -0,0 +1,10 @@
get:
tags: [Public]
summary: Deposit info
responses:
"200":
description: Lightning address and LNURLp
content:
application/json:
schema:
$ref: "../components/schemas/faucet.yaml#/DepositInfo"

View File

@@ -0,0 +1,14 @@
get:
tags: [Public]
summary: Health check
responses:
"200":
description: OK
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: ok

View File

@@ -0,0 +1,16 @@
get:
tags: [Public]
summary: Faucet stats
responses:
"200":
description: Stats (balance, paid, claims)
content:
application/json:
schema:
$ref: "../components/schemas/faucet.yaml#/Stats"
"500":
description: Internal error
content:
application/json:
schema:
$ref: "../components/schemas/common.yaml#/ApiError"

View File

@@ -0,0 +1,18 @@
post:
tags: [User]
summary: Refresh Nostr profile (kind 0)
security:
- BearerAuth: []
responses:
"200":
description: lightning_address and name
content:
application/json:
schema:
$ref: "../components/schemas/user.yaml#/UserProfile"
"500":
description: Profile fetch failed
content:
application/json:
schema:
$ref: "../components/schemas/common.yaml#/ApiError"