openapi.yaml
Rama main · réplica de lectura del repositorio original.
openapi: 3.0.3
info:
title: Raptor API
description: |
Self-hosted webhook/email/DNS capture & inspection. This document is the
spec-first source of truth for the versioned management API under `/api/v1`.
The SPA is a pure client of it.
**Authentication.** When `--require-auth` is enabled, send `Api-Key: <uuid>`.
With no key configured the API is open (first-run bootstrap mode).
version: "1.0"
servers:
- url: /api/v1
paths:
/groups:
get:
summary: List groups
operationId: listGroups
responses:
"200":
description: All groups
content:
application/json:
schema:
type: object
properties:
data:
type: array
items: { $ref: "#/components/schemas/Group" }
post:
summary: Create a group
operationId: createGroup
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [name]
properties:
name: { type: string }
color: { type: string }
responses:
"201":
description: Created group
content:
application/json:
schema: { $ref: "#/components/schemas/Group" }
/groups/{groupID}:
parameters:
- { name: groupID, in: path, required: true, schema: { type: string } }
put:
summary: Update a group
operationId: updateGroup
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name: { type: string }
color: { type: string }
responses:
"200":
description: Updated group
content:
application/json:
schema: { $ref: "#/components/schemas/Group" }
delete:
summary: Delete a group (tokens are kept and detached)
operationId: deleteGroup
responses:
"204": { description: Deleted }
"404": { description: Not found }
/schedules:
get:
summary: List schedules
operationId: listSchedules
responses:
"200":
description: Schedules
content:
application/json:
schema:
type: object
properties:
data: { type: array, items: { $ref: "#/components/schemas/Schedule" } }
post:
summary: Create a schedule
operationId: createSchedule
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/ScheduleInput" }
responses:
"201":
description: Created schedule
content:
application/json:
schema: { $ref: "#/components/schemas/Schedule" }
/schedules/{scheduleID}:
parameters:
- { name: scheduleID, in: path, required: true, schema: { type: string } }
get:
summary: Get a schedule
operationId: getSchedule
responses:
"200":
description: Schedule
content:
application/json:
schema: { $ref: "#/components/schemas/Schedule" }
put:
summary: Update a schedule
operationId: updateSchedule
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/ScheduleInput" }
responses:
"200":
description: Updated schedule
content:
application/json:
schema: { $ref: "#/components/schemas/Schedule" }
delete:
summary: Delete a schedule
operationId: deleteSchedule
responses:
"204": { description: Deleted }
/schedules/{scheduleID}/runs:
parameters:
- { name: scheduleID, in: path, required: true, schema: { type: string } }
get:
summary: List a schedule's run history
operationId: listScheduleRuns
responses:
"200":
description: Runs
content:
application/json:
schema:
type: object
properties:
data: { type: array, items: { $ref: "#/components/schemas/ScheduleRun" } }
/schedules/{scheduleID}/run:
parameters:
- { name: scheduleID, in: path, required: true, schema: { type: string } }
post:
summary: Run a schedule immediately
operationId: runScheduleNow
responses:
"200":
description: Run result
content:
application/json:
schema: { $ref: "#/components/schemas/ScheduleRun" }
/tokens/{tokenID}/replay:
parameters:
- $ref: "#/components/parameters/TokenID"
post:
summary: Replay a subset of captured requests to a target URL
operationId: replayRequests
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [target_url]
properties:
target_url: { type: string }
q: { type: string, description: "search DSL to select the subset" }
date_from: { type: string }
date_to: { type: string }
limit: { type: integer }
responses:
"200":
description: Replay counts
content:
application/json:
schema:
type: object
properties:
replayed: { type: integer }
failed: { type: integer }
/auth/status:
get:
summary: Auth/bootstrap status and current user
operationId: authStatus
responses:
"200":
description: Status
content:
application/json:
schema:
type: object
properties:
bootstrapped: { type: boolean }
require_auth: { type: boolean }
allow_registration: { type: boolean }
authenticated: { type: boolean }
user: { $ref: "#/components/schemas/User" }
/auth/register:
post:
summary: Register an account (first one becomes admin; adopts anonymous URLs)
operationId: register
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/Credentials" }
responses:
"201": { description: Account created and signed in }
"403": { description: Registration disabled }
/auth/bootstrap:
post:
summary: Create the first admin (only when no users exist)
operationId: bootstrap
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/Credentials" }
responses:
"201": { description: Admin created and signed in }
"409": { description: Already initialised }
/auth/login:
post:
summary: Sign in (sets a session cookie)
operationId: login
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/Credentials" }
responses:
"200": { description: Signed in }
"401": { description: Invalid credentials }
/auth/logout:
post:
summary: Sign out
operationId: logout
responses:
"204": { description: Signed out }
/auth/me:
get:
summary: Current authenticated user
operationId: me
responses:
"200":
description: User
content:
application/json:
schema: { $ref: "#/components/schemas/User" }
"401": { description: Not authenticated }
/account/api-keys:
get:
summary: List the current user's API keys
operationId: listAPIKeys
responses:
"200":
description: API keys
content:
application/json:
schema:
type: object
properties:
data: { type: array, items: { $ref: "#/components/schemas/APIKey" } }
post:
summary: Create an API key (plaintext returned once)
operationId: createAPIKey
requestBody:
required: false
content:
application/json:
schema:
type: object
properties: { name: { type: string } }
responses:
"201":
description: Created key (the `key` field is shown only here)
content:
application/json:
schema:
type: object
properties:
key: { type: string }
api_key: { $ref: "#/components/schemas/APIKey" }
/account/api-keys/{keyID}:
parameters:
- { name: keyID, in: path, required: true, schema: { type: string } }
delete:
summary: Revoke an API key
operationId: deleteAPIKey
responses:
"204": { description: Revoked }
/users:
get:
summary: List users (admin)
operationId: listUsers
responses:
"200":
description: Users
content:
application/json:
schema:
type: object
properties:
data: { type: array, items: { $ref: "#/components/schemas/User" } }
"403": { description: Admin role required }
post:
summary: Create a user (admin)
operationId: createUser
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [email, password]
properties:
email: { type: string }
password: { type: string }
role: { type: string, enum: [admin, user] }
responses:
"201":
description: Created user
content:
application/json:
schema: { $ref: "#/components/schemas/User" }
/users/{userID}:
parameters:
- { name: userID, in: path, required: true, schema: { type: string } }
put:
summary: Update a user (admin)
operationId: updateUser
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
email: { type: string }
password: { type: string }
role: { type: string, enum: [admin, user] }
responses:
"200":
description: Updated user
content:
application/json:
schema: { $ref: "#/components/schemas/User" }
delete:
summary: Delete a user (admin)
operationId: deleteUser
responses:
"204": { description: Deleted }
/action-types:
get:
summary: List available Custom Action type names
operationId: listActionTypes
responses:
"200":
description: Action type names
content:
application/json:
schema:
type: object
properties:
data: { type: array, items: { type: string } }
/tokens/{tokenID}/actions:
parameters:
- $ref: "#/components/parameters/TokenID"
get:
summary: List a token's Custom Actions (in execution order)
operationId: listActions
responses:
"200":
description: Actions
content:
application/json:
schema:
type: object
properties:
data: { type: array, items: { $ref: "#/components/schemas/Action" } }
post:
summary: Add a Custom Action
operationId: createAction
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/ActionInput" }
responses:
"201":
description: Created action
content:
application/json:
schema: { $ref: "#/components/schemas/Action" }
/tokens/{tokenID}/actions/{actionID}:
parameters:
- $ref: "#/components/parameters/TokenID"
- { name: actionID, in: path, required: true, schema: { type: string } }
put:
summary: Update a Custom Action
operationId: updateAction
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/ActionInput" }
responses:
"200":
description: Updated action
content:
application/json:
schema: { $ref: "#/components/schemas/Action" }
delete:
summary: Delete a Custom Action
operationId: deleteAction
responses:
"204": { description: Deleted }
/tokens/{tokenID}/test-action:
parameters:
- $ref: "#/components/parameters/TokenID"
post:
summary: Test a single action definition against the latest request
operationId: testAction
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/ActionInput" }
responses:
"200":
description: Test result (output, error, variables, response)
content:
application/json:
schema: { type: object }
/tokens/{tokenID}/requests/{requestID}/action-runs:
parameters:
- $ref: "#/components/parameters/TokenID"
- $ref: "#/components/parameters/RequestID"
get:
summary: List the action run log for a request
operationId: listActionRuns
responses:
"200":
description: Action runs
content:
application/json:
schema:
type: object
properties:
data: { type: array, items: { $ref: "#/components/schemas/ActionRun" } }
/tokens/{tokenID}/requests/{requestID}/response:
parameters:
- $ref: "#/components/parameters/TokenID"
- $ref: "#/components/parameters/RequestID"
post:
summary: Supply the response for a pending request (CLI listen flow)
operationId: setResponse
description: >
When the token has `listen > 0`, a capture is held open until this
endpoint supplies a response. Body may be base64 (`content`) or raw
(`content_text`).
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
status: { type: integer }
content: { type: string, description: "base64-encoded body" }
content_text: { type: string, description: "raw body (alternative to content)" }
headers: { type: object, additionalProperties: { type: string } }
responses:
"204": { description: Response delivered }
"404": { description: No request is waiting (not listening / already responded) }
/tokens/{tokenID}/requests/{requestID}/execute:
parameters:
- $ref: "#/components/parameters/TokenID"
- $ref: "#/components/parameters/RequestID"
post:
summary: Replay the action chain against a stored request
operationId: executeChain
responses:
"200":
description: Resulting action runs
content:
application/json:
schema:
type: object
properties:
data: { type: array, items: { $ref: "#/components/schemas/ActionRun" } }
/tokens:
get:
summary: List tokens
operationId: listTokens
responses:
"200":
description: All tokens
content:
application/json:
schema:
type: object
properties:
data:
type: array
items: { $ref: "#/components/schemas/Token" }
post:
summary: Create a token
operationId: createToken
requestBody:
required: false
content:
application/json:
schema: { $ref: "#/components/schemas/TokenInput" }
responses:
"201":
description: Created token
content:
application/json:
schema: { $ref: "#/components/schemas/Token" }
"409": { description: Alias already in use }
/tokens/{tokenID}:
parameters:
- $ref: "#/components/parameters/TokenID"
get:
summary: Get a token
operationId: getToken
responses:
"200":
description: Token
content:
application/json:
schema: { $ref: "#/components/schemas/Token" }
"404": { description: Not found }
put:
summary: Update a token
operationId: updateToken
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/TokenInput" }
responses:
"200":
description: Updated token
content:
application/json:
schema: { $ref: "#/components/schemas/Token" }
delete:
summary: Delete a token and all its data
operationId: deleteToken
responses:
"204": { description: Deleted }
"404": { description: Not found }
/tokens/{tokenID}/stream:
parameters:
- $ref: "#/components/parameters/TokenID"
get:
summary: Stream newly captured requests (Server-Sent Events)
operationId: streamRequests
description: |
Opens a long-lived `text/event-stream`. Each captured request is sent as
an `event: request` with the JSON request object as `data`. Comment lines
(`: ping`) are heartbeats.
responses:
"200":
description: SSE stream
content:
text/event-stream:
schema: { type: string }
/tokens/{tokenID}/requests:
parameters:
- $ref: "#/components/parameters/TokenID"
get:
summary: List captured requests (paged, newest first)
operationId: listRequests
parameters:
- { name: page, in: query, schema: { type: integer, default: 1 } }
- { name: per_page, in: query, schema: { type: integer, default: 50, maximum: 100 } }
- name: q
in: query
description: >
Search DSL. Free text matches content; field filters include
`content:`, `method:`, `type:`, `ip:`, `host:`, `url:`, `query:`,
`headers.<key>:`, `_exists_:<field>`, and
`created_at:[* TO now-14d]`. Terms are ANDed; quote values with spaces.
schema: { type: string }
- { name: date_from, in: query, description: "ISO date/datetime lower bound", schema: { type: string } }
- { name: date_to, in: query, description: "ISO date/datetime upper bound", schema: { type: string } }
responses:
"200":
description: Page of requests
content:
application/json:
schema:
type: object
properties:
data:
type: array
items: { $ref: "#/components/schemas/Request" }
total: { type: integer }
page: { type: integer }
per_page: { type: integer }
delete:
summary: Delete requests for the token (all, or a `q`/`date_from`/`date_to` subset)
operationId: deleteAllRequests
parameters:
- { name: q, in: query, description: "search DSL; deletes only matching requests", schema: { type: string } }
- { name: date_from, in: query, schema: { type: string } }
- { name: date_to, in: query, schema: { type: string } }
responses:
"200":
description: Number deleted
content:
application/json:
schema:
type: object
properties:
deleted: { type: integer }
/tokens/{tokenID}/requests.csv:
parameters:
- $ref: "#/components/parameters/TokenID"
get:
summary: Export all captured requests as CSV
operationId: exportCSV
responses:
"200":
description: CSV download
content:
text/csv:
schema: { type: string }
/tokens/{tokenID}/requests/latest:
parameters:
- $ref: "#/components/parameters/TokenID"
get:
summary: Get the most recent request
operationId: latestRequest
responses:
"200":
description: Request
content:
application/json:
schema: { $ref: "#/components/schemas/Request" }
"404": { description: No requests yet }
/tokens/{tokenID}/requests/{requestID}:
parameters:
- $ref: "#/components/parameters/TokenID"
- $ref: "#/components/parameters/RequestID"
get:
summary: Get a single request
operationId: getRequest
responses:
"200":
description: Request
content:
application/json:
schema: { $ref: "#/components/schemas/Request" }
"404": { description: Not found }
delete:
summary: Delete a single request
operationId: deleteRequest
responses:
"204": { description: Deleted }
"404": { description: Not found }
/tokens/{tokenID}/requests/{requestID}/raw:
parameters:
- $ref: "#/components/parameters/TokenID"
- $ref: "#/components/parameters/RequestID"
get:
summary: Get the raw HTTP representation of a request
operationId: rawRequest
responses:
"200":
description: Raw request
content:
text/plain:
schema: { type: string }
/tokens/{tokenID}/requests/{requestID}/files/{fileID}:
parameters:
- $ref: "#/components/parameters/TokenID"
- $ref: "#/components/parameters/RequestID"
- { name: fileID, in: path, required: true, schema: { type: string } }
get:
summary: Download a request's attached file
operationId: downloadFile
responses:
"200":
description: File blob
content:
application/octet-stream:
schema: { type: string, format: binary }
"404": { description: Not found }
components:
parameters:
TokenID:
name: tokenID
in: path
required: true
description: Token UUID or alias
schema: { type: string }
RequestID:
name: requestID
in: path
required: true
schema: { type: string }
schemas:
TokenInput:
type: object
properties:
alias: { type: string }
default_status: { type: integer, default: 200 }
default_content: { type: string }
default_content_type: { type: string, default: text/plain }
timeout: { type: integer, description: "drives the 100/timeout rpm rate limit; 0 = unlimited" }
cors: { type: boolean }
expiry: { type: integer, description: "TTL seconds from creation; 0 = never" }
actions: { type: boolean }
request_limit: { type: integer, description: "max stored requests; 0 = unlimited" }
description: { type: string }
listen: { type: integer }
redirect: { type: string }
group_id: { type: string }
clone_from: { type: string, description: "copy settings from an existing token UUID" }
Token:
type: object
properties:
uuid: { type: string }
alias: { type: string }
url: { type: string, description: "copyable capture URL" }
default_status: { type: integer }
default_content: { type: string }
default_content_type: { type: string }
timeout: { type: integer }
cors: { type: boolean }
expiry: { type: integer }
actions: { type: boolean }
request_limit: { type: integer }
description: { type: string }
listen: { type: integer }
redirect: { type: string }
group_id: { type: string }
premium: { type: boolean }
has_password: { type: boolean }
created_at: { type: string, format: date-time }
updated_at: { type: string, format: date-time }
latest_request_at: { type: string, format: date-time, nullable: true }
Request:
type: object
properties:
uuid: { type: string }
token_id: { type: string }
type: { type: string, enum: [web, email, dns] }
method: { type: string }
ip: { type: string }
hostname: { type: string }
user_agent: { type: string }
content: { type: string }
query: { type: object, additionalProperties: { type: array, items: { type: string } } }
headers: { type: object, additionalProperties: { type: array, items: { type: string } } }
url: { type: string }
size: { type: integer }
sorting: { type: integer, format: int64 }
files:
type: array
items: { $ref: "#/components/schemas/File" }
created_at: { type: string, format: date-time }
# Email-specific fields (type == email)
sender: { type: string }
message_id: { type: string }
destinations: { type: string }
subject: { type: string }
text_content: { type: string }
checks:
type: object
description: "DKIM/SPF/DMARC results, e.g. {\"dkim\":\"pass\",\"spf\":\"fail\"}"
additionalProperties: { type: string }
File:
type: object
properties:
id: { type: string }
request_id: { type: string }
filename: { type: string }
content_type: { type: string }
size: { type: integer }
Group:
type: object
properties:
id: { type: string }
name: { type: string }
color: { type: string }
created_at: { type: string, format: date-time }
ActionInput:
type: object
required: [type]
properties:
type:
type: string
description: "set_variable | modify_response | conditions | extract_json | extract_regex | http_request | script | dont_save | stop"
name: { type: string }
position: { type: integer }
disabled: { type: boolean }
parameters: { type: object, description: "type-specific parameters" }
Action:
allOf:
- $ref: "#/components/schemas/ActionInput"
- type: object
properties:
uuid: { type: string }
token_id: { type: string }
created_at: { type: string, format: date-time }
updated_at: { type: string, format: date-time }
ActionRun:
type: object
properties:
id: { type: string }
request_id: { type: string }
action_id: { type: string }
action_type: { type: string }
action_name: { type: string }
position: { type: integer }
output: { type: string }
error: { type: string }
created_at: { type: string, format: date-time }
ScheduleInput:
type: object
required: [cron]
properties:
token_id: { type: string }
name: { type: string }
cron: { type: string, description: "5-field cron expression" }
target_url: { type: string }
method: { type: string }
body: { type: string }
run_actions: { type: boolean, description: "run the token's action chain instead of an HTTP check" }
expect_status: { type: integer, description: "0 = any 2xx is OK" }
keyword: { type: string, description: "alert if the response body lacks this" }
check_ssl: { type: boolean }
ssl_days: { type: integer }
notify_url: { type: string, description: "Shoutrrr alert URL; write-only, never returned" }
enabled: { type: boolean }
Schedule:
type: object
properties:
uuid: { type: string }
token_id: { type: string }
name: { type: string }
cron: { type: string }
target_url: { type: string }
method: { type: string }
body: { type: string }
run_actions: { type: boolean }
expect_status: { type: integer }
keyword: { type: string }
check_ssl: { type: boolean }
ssl_days: { type: integer }
has_notify: { type: boolean, description: "whether an alert URL is configured (masked)" }
enabled: { type: boolean }
last_run: { type: string, format: date-time, nullable: true }
next_run: { type: string, format: date-time, nullable: true }
last_status: { type: string, enum: [ok, alert, error] }
last_message: { type: string }
created_at: { type: string, format: date-time }
updated_at: { type: string, format: date-time }
ScheduleRun:
type: object
properties:
id: { type: string }
schedule_id: { type: string }
status: { type: string, enum: [ok, alert, error] }
status_code: { type: integer }
message: { type: string }
duration_ms: { type: integer }
created_at: { type: string, format: date-time }
Credentials:
type: object
required: [email, password]
properties:
email: { type: string }
password: { type: string }
User:
type: object
properties:
id: { type: string }
email: { type: string }
role: { type: string, enum: [admin, user] }
created_at: { type: string, format: date-time }
updated_at: { type: string, format: date-time }
APIKey:
type: object
properties:
id: { type: string }
user_id: { type: string }
name: { type: string }
last_used_at: { type: string, format: date-time, nullable: true }
created_at: { type: string, format: date-time }
securitySchemes:
ApiKey:
type: apiKey
in: header
name: Api-Key