Files
WRNexusJS/services/managed-captcha/docs/openapi.yaml
2026-07-29 12:51:10 +05:30

213 lines
6.8 KiB
YAML

openapi: 3.1.0
info:
title: WRNexus Managed CAPTCHA API
version: 0.5.0
servers:
- url: https://captcha.example.com
paths:
/v1/challenges:
post:
summary: Create a public challenge
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [siteKey, action]
properties:
siteKey: { type: string }
action: { type: string }
type:
{
type: string,
enum:
[
number,
alpha,
alphanumeric,
calculation,
image,
honeypot,
timing,
not-robot,
],
}
presentation: { type: string, enum: [visual, audio, invisible] }
difficulty: { type: string, enum: [easy, normal, hard] }
disturbance: { type: integer, minimum: 25, maximum: 75, default: 50 }
imageStyle:
type: string
default: random
enum:
[
random,
classic,
collision,
snow,
corrosion,
spiderweb,
cross-shadow,
split,
split2,
cut,
darts,
distortion,
stitch,
striped,
wave,
grid-noise,
scribble,
pixel,
broken-lines,
]
allowedStyles:
oneOf:
- { type: string, description: Comma-separated renderer names }
- type: array
items: { type: string }
excludedStyles:
oneOf:
- { type: string, description: Comma-separated renderer names }
- type: array
items: { type: string }
randomizeStyle: { type: boolean, default: false }
locale: { type: string }
responses:
"201":
description: Challenge created
content:
application/json:
schema: { $ref: "#/components/schemas/Challenge" }
"403": { description: Invalid site key or hostname }
"429": { description: Project quota exceeded }
/v1/solve:
post:
summary: Solve a public challenge and receive a temporary response token
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [challengeId, action]
properties:
challengeId: { type: string }
action: { type: string }
answer: { oneOf: [{ type: string }, { type: number }] }
selections: { type: array, items: { type: string } }
honeypot: { type: string }
timingToken: { type: string }
responses:
"200":
description: Challenge solved
content:
application/json:
schema: { $ref: "#/components/schemas/Verification" }
"400": { description: Challenge rejected }
/v1/verify:
post:
summary: Verify and consume a response token on the application server
security: [{ projectSecret: [] }]
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [responseToken, action]
properties:
responseToken: { type: string }
action: { type: string }
hostname: { type: string }
sessionId: { type: string }
responses:
"200":
description: Token accepted and consumed
content:
application/json:
schema: { $ref: "#/components/schemas/Verification" }
"400": { description: Token invalid, expired, mismatched, or already used }
"401": { description: Invalid project secret }
/v1/projects:
get:
summary: List projects
security: [{ adminToken: [] }]
responses:
"200": { description: Project list without secrets }
post:
summary: Create a project and return keys once
security: [{ adminToken: [] }]
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [name]
properties:
name: { type: string }
allowedHostnames: { type: array, items: { type: string } }
monthlyQuota: { type: integer, minimum: 1 }
responses:
"201": { description: Project and initial keys }
/v1/projects/{id}/rotate-secret:
post:
summary: Rotate a project verification secret
security: [{ adminToken: [] }]
parameters:
- in: path
name: id
required: true
schema: { type: string }
responses:
"200": { description: New secret returned once }
"404": { description: Project not found }
components:
securitySchemes:
projectSecret:
type: http
scheme: bearer
adminToken:
type: http
scheme: bearer
schemas:
Challenge:
type: object
required:
[id, provider, type, presentation, action, prompt, createdAt, expiresAt, responseField]
properties:
id: { type: string }
provider: { type: string }
type: { type: string }
presentation: { type: string }
action: { type: string }
prompt: { type: string }
image: { type: string }
audioUrl: { type: string }
items: { type: array, items: { type: object } }
createdAt: { type: integer }
expiresAt: { type: integer }
responseField: { type: string }
metadata:
type: object
properties:
difficulty: { type: string }
disturbance: { type: integer }
imageStyle: { type: string }
requestedImageStyle: { type: string }
imageStylePool:
type: array
items: { type: string }
Verification:
type: object
required: [success, provider, action]
properties:
success: { type: boolean }
provider: { type: string }
action: { type: string }
code: { type: string }
message: { type: string }
responseToken: { type: string }
expiresAt: { type: integer }