1290 lines
35 KiB
JSON
1290 lines
35 KiB
JSON
{
|
|
"api_meta": {
|
|
"name": "Managinator Backend API",
|
|
"overview": "Token-gated Flask service for managing investment profiles, users, and scrapers.",
|
|
"base_url_example": "http://localhost:8000",
|
|
"default_headers": {
|
|
"Content-Type": "application/json"
|
|
},
|
|
"cors": {
|
|
"allow_origin": "*",
|
|
"allow_credentials": true,
|
|
"notes": "Server responds to OPTIONS preflight without authentication."
|
|
}
|
|
},
|
|
"authentication": {
|
|
"strategy": "session_token",
|
|
"login_endpoint": "/auth/login",
|
|
"session_duration_seconds": 86400,
|
|
"header": "X-Session-Token",
|
|
"credential_source": "Clients must send the server-side AUTH_TOKEN value in the login body to receive a session token.",
|
|
"notes": [
|
|
"All endpoints except POST /auth/login require a valid X-Session-Token header.",
|
|
"Session tokens expire 24 hours after issuance; expired tokens trigger 401 responses and must be refreshed via /auth/login."
|
|
]
|
|
},
|
|
"conventions": {
|
|
"datetime_format": "Use ISO 8601 strings with timezone. Responses normalize to UTC with trailing Z.",
|
|
"boolean_input": "Send JSON booleans true/false. The backend also accepts 1/0 and common string equivalents, but clients should prefer booleans.",
|
|
"integer_input": "Integer fields accept JSON numbers. Numeric strings will be coerced server-side but should be avoided.",
|
|
"null_handling": "Fields documented as nullable accept JSON null and will persist as SQL NULL.",
|
|
"error_responses": {
|
|
"typical_status_codes": [400, 401, 404, 409, 503],
|
|
"body_format": "Flask default HTTP error responses; body may be plain text or HTML containing the description. Rely on HTTP status and message."
|
|
}
|
|
},
|
|
"schemas": {
|
|
"Session": {
|
|
"description": "Session token issued after successful login.",
|
|
"fields": [
|
|
{
|
|
"name": "session_token",
|
|
"type": "string",
|
|
"nullable": false,
|
|
"read_only": true,
|
|
"description": "Opaque token to supply via X-Session-Token header."
|
|
},
|
|
{
|
|
"name": "expires_at",
|
|
"type": "datetime",
|
|
"nullable": false,
|
|
"read_only": true,
|
|
"description": "UTC expiry timestamp in ISO 8601 format with trailing Z."
|
|
}
|
|
]
|
|
},
|
|
"Profile": {
|
|
"description": "Investment profile descriptor persisted in users_investmentprofile.",
|
|
"fields": [
|
|
{
|
|
"name": "profile_id",
|
|
"type": "uuid",
|
|
"nullable": false,
|
|
"read_only": false,
|
|
"description": "Primary key. Optional on create; autogenerated when omitted."
|
|
},
|
|
{
|
|
"name": "name",
|
|
"type": "string",
|
|
"nullable": false,
|
|
"read_only": false,
|
|
"description": "Human-readable profile label."
|
|
},
|
|
{
|
|
"name": "description",
|
|
"type": "string",
|
|
"nullable": true,
|
|
"read_only": false,
|
|
"description": "Optional free-form description. Empty string preserved."
|
|
},
|
|
{
|
|
"name": "criteria",
|
|
"type": "json",
|
|
"nullable": false,
|
|
"read_only": false,
|
|
"description": "Arbitrary JSON object/array describing selection rules."
|
|
},
|
|
{
|
|
"name": "created_at",
|
|
"type": "datetime",
|
|
"nullable": false,
|
|
"read_only": false,
|
|
"description": "Creation timestamp. Defaults to current UTC when omitted."
|
|
},
|
|
{
|
|
"name": "is_active",
|
|
"type": "boolean",
|
|
"nullable": false,
|
|
"read_only": false,
|
|
"description": "Activation flag. Defaults to true on create."
|
|
}
|
|
]
|
|
},
|
|
"User": {
|
|
"description": "Auth user record persisted in auth_user.",
|
|
"fields": [
|
|
{
|
|
"name": "id",
|
|
"type": "integer",
|
|
"nullable": false,
|
|
"read_only": true,
|
|
"description": "Database primary key."
|
|
},
|
|
{
|
|
"name": "username",
|
|
"type": "string",
|
|
"nullable": false,
|
|
"read_only": false,
|
|
"description": "Unique login name."
|
|
},
|
|
{
|
|
"name": "password",
|
|
"type": "string",
|
|
"nullable": false,
|
|
"read_only": false,
|
|
"description": "Raw password value inserted as-is. Not returned in responses."
|
|
},
|
|
{
|
|
"name": "first_name",
|
|
"type": "string",
|
|
"nullable": false,
|
|
"read_only": false,
|
|
"description": "User first name."
|
|
},
|
|
{
|
|
"name": "last_name",
|
|
"type": "string",
|
|
"nullable": false,
|
|
"read_only": false,
|
|
"description": "User last name."
|
|
},
|
|
{
|
|
"name": "email",
|
|
"type": "string",
|
|
"nullable": false,
|
|
"read_only": false,
|
|
"description": "User email address."
|
|
},
|
|
{
|
|
"name": "is_superuser",
|
|
"type": "boolean",
|
|
"nullable": false,
|
|
"read_only": false,
|
|
"description": "Administrative superuser flag."
|
|
},
|
|
{
|
|
"name": "is_staff",
|
|
"type": "boolean",
|
|
"nullable": false,
|
|
"read_only": false,
|
|
"description": "Staff membership flag."
|
|
},
|
|
{
|
|
"name": "is_active",
|
|
"type": "boolean",
|
|
"nullable": false,
|
|
"read_only": false,
|
|
"description": "Account enabled flag."
|
|
},
|
|
{
|
|
"name": "date_joined",
|
|
"type": "datetime",
|
|
"nullable": false,
|
|
"read_only": false,
|
|
"description": "Account creation timestamp. Defaults to current UTC when omitted."
|
|
},
|
|
{
|
|
"name": "last_login",
|
|
"type": "datetime",
|
|
"nullable": true,
|
|
"read_only": false,
|
|
"description": "Most recent login timestamp."
|
|
}
|
|
]
|
|
},
|
|
"Scraper": {
|
|
"description": "Scraper configuration persisted in scraper table.",
|
|
"fields": [
|
|
{
|
|
"name": "id",
|
|
"type": "string",
|
|
"nullable": false,
|
|
"read_only": false,
|
|
"description": "Primary key identifier."
|
|
},
|
|
{
|
|
"name": "params",
|
|
"type": "string",
|
|
"nullable": true,
|
|
"read_only": false,
|
|
"description": "Serialized scraper parameters."
|
|
},
|
|
{
|
|
"name": "last_seen_days",
|
|
"type": "integer",
|
|
"nullable": true,
|
|
"read_only": false,
|
|
"description": "Number of days since listings were last seen."
|
|
},
|
|
{
|
|
"name": "first_seen_days",
|
|
"type": "integer",
|
|
"nullable": true,
|
|
"read_only": false,
|
|
"description": "Number of days since listings were first seen."
|
|
},
|
|
{
|
|
"name": "frequency",
|
|
"type": "string",
|
|
"nullable": true,
|
|
"read_only": false,
|
|
"description": "Cron or human-readable frequency descriptor."
|
|
},
|
|
{
|
|
"name": "task_name",
|
|
"type": "string",
|
|
"nullable": true,
|
|
"read_only": false,
|
|
"description": "Associated task identifier."
|
|
},
|
|
{
|
|
"name": "enabled",
|
|
"type": "integer",
|
|
"nullable": true,
|
|
"read_only": false,
|
|
"description": "1/0 flag for activation. Stored as integer."
|
|
},
|
|
{
|
|
"name": "property_types",
|
|
"type": "string",
|
|
"nullable": true,
|
|
"read_only": false,
|
|
"description": "Comma-separated property type filters."
|
|
},
|
|
{
|
|
"name": "page_size",
|
|
"type": "integer",
|
|
"nullable": true,
|
|
"read_only": false,
|
|
"description": "Listings fetched per page."
|
|
},
|
|
{
|
|
"name": "max_pages",
|
|
"type": "integer",
|
|
"nullable": true,
|
|
"read_only": false,
|
|
"description": "Maximum number of pages to crawl."
|
|
},
|
|
{
|
|
"name": "enrich_llm",
|
|
"type": "integer",
|
|
"nullable": true,
|
|
"read_only": false,
|
|
"description": "Toggle for LLM enrichment (1 enabled, 0 disabled)."
|
|
},
|
|
{
|
|
"name": "only_match",
|
|
"type": "integer",
|
|
"nullable": true,
|
|
"read_only": false,
|
|
"description": "Toggle for strict matching (1 enabled, 0 disabled)."
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"endpoints": [
|
|
{
|
|
"operation_id": "login",
|
|
"method": "POST",
|
|
"path": "/auth/login",
|
|
"authenticated": false,
|
|
"description": "Exchange the static AUTH_TOKEN for a time-limited session token.",
|
|
"request": {
|
|
"headers": {
|
|
"Content-Type": {
|
|
"type": "string",
|
|
"required": true,
|
|
"example": "application/json"
|
|
}
|
|
},
|
|
"body": {
|
|
"type": "object",
|
|
"required_fields": ["token"],
|
|
"fields": {
|
|
"token": {
|
|
"type": "string",
|
|
"nullable": false,
|
|
"description": "Server-configured AUTH_TOKEN value."
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"201": {
|
|
"description": "Session token issued.",
|
|
"body": {
|
|
"$ref": "#/schemas/Session"
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Token missing."
|
|
},
|
|
"401": {
|
|
"description": "Submitted token invalid."
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"operation_id": "listProfiles",
|
|
"method": "GET",
|
|
"path": "/profiles",
|
|
"authenticated": true,
|
|
"description": "List all investment profiles ordered by most recent creation.",
|
|
"request": {
|
|
"headers": {
|
|
"X-Session-Token": {
|
|
"type": "string",
|
|
"required": true,
|
|
"description": "Session token from /auth/login."
|
|
}
|
|
},
|
|
"path_params": [],
|
|
"query_params": [],
|
|
"body": null
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Array of profiles.",
|
|
"body": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/schemas/Profile"
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Missing or invalid session."
|
|
},
|
|
"503": {
|
|
"description": "Database unavailable."
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"operation_id": "getProfile",
|
|
"method": "GET",
|
|
"path": "/profiles/<profile_id>",
|
|
"authenticated": true,
|
|
"description": "Retrieve a single profile by UUID.",
|
|
"request": {
|
|
"headers": {
|
|
"X-Session-Token": {
|
|
"type": "string",
|
|
"required": true,
|
|
"description": "Session token from /auth/login."
|
|
}
|
|
},
|
|
"path_params": [
|
|
{
|
|
"name": "profile_id",
|
|
"type": "uuid",
|
|
"required": true,
|
|
"description": "Profile identifier."
|
|
}
|
|
],
|
|
"query_params": [],
|
|
"body": null
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Profile payload.",
|
|
"body": {
|
|
"$ref": "#/schemas/Profile"
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Missing or invalid session."
|
|
},
|
|
"404": {
|
|
"description": "Profile not found."
|
|
},
|
|
"503": {
|
|
"description": "Database unavailable."
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"operation_id": "createProfile",
|
|
"method": "POST",
|
|
"path": "/profiles",
|
|
"authenticated": true,
|
|
"description": "Create a new investment profile.",
|
|
"request": {
|
|
"headers": {
|
|
"Content-Type": {
|
|
"type": "string",
|
|
"required": true,
|
|
"example": "application/json"
|
|
},
|
|
"X-Session-Token": {
|
|
"type": "string",
|
|
"required": true,
|
|
"description": "Session token from /auth/login."
|
|
}
|
|
},
|
|
"body": {
|
|
"type": "object",
|
|
"required_fields": ["name", "criteria"],
|
|
"fields": {
|
|
"profile_id": {
|
|
"type": "uuid",
|
|
"nullable": false,
|
|
"description": "Optional explicit UUID. Auto-generated when omitted."
|
|
},
|
|
"name": {
|
|
"type": "string",
|
|
"nullable": false,
|
|
"description": "Profile name."
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"nullable": true,
|
|
"description": "Optional description. Use null to clear."
|
|
},
|
|
"criteria": {
|
|
"type": "json",
|
|
"nullable": false,
|
|
"description": "Required JSON criteria payload."
|
|
},
|
|
"created_at": {
|
|
"type": "datetime",
|
|
"nullable": false,
|
|
"description": "Optional creation timestamp. Defaults to now (UTC)."
|
|
},
|
|
"is_active": {
|
|
"type": "boolean",
|
|
"nullable": false,
|
|
"description": "Defaults to true."
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"201": {
|
|
"description": "Profile created.",
|
|
"body": {
|
|
"$ref": "#/schemas/Profile"
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Validation failure (missing criteria, invalid field formats, or empty request)."
|
|
},
|
|
"401": {
|
|
"description": "Missing or invalid session."
|
|
},
|
|
"409": {
|
|
"description": "Constraint violation (e.g., duplicate profile_id)."
|
|
},
|
|
"503": {
|
|
"description": "Database unavailable."
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"operation_id": "updateProfile",
|
|
"method": "PUT",
|
|
"path": "/profiles/<profile_id>",
|
|
"authenticated": true,
|
|
"description": "Update mutable fields on an existing profile.",
|
|
"request": {
|
|
"headers": {
|
|
"Content-Type": {
|
|
"type": "string",
|
|
"required": true,
|
|
"example": "application/json"
|
|
},
|
|
"X-Session-Token": {
|
|
"type": "string",
|
|
"required": true,
|
|
"description": "Session token from /auth/login."
|
|
}
|
|
},
|
|
"path_params": [
|
|
{
|
|
"name": "profile_id",
|
|
"type": "uuid",
|
|
"required": true,
|
|
"description": "Profile identifier."
|
|
}
|
|
],
|
|
"body": {
|
|
"type": "object",
|
|
"allowed_fields": [
|
|
"name",
|
|
"description",
|
|
"criteria",
|
|
"created_at",
|
|
"is_active"
|
|
],
|
|
"min_fields": 1,
|
|
"fields": {
|
|
"name": {
|
|
"type": "string",
|
|
"nullable": false,
|
|
"description": "New profile name."
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"nullable": true,
|
|
"description": "Use null to clear description."
|
|
},
|
|
"criteria": {
|
|
"type": "json",
|
|
"nullable": false,
|
|
"description": "Updated criteria JSON."
|
|
},
|
|
"created_at": {
|
|
"type": "datetime",
|
|
"nullable": false,
|
|
"description": "New creation timestamp."
|
|
},
|
|
"is_active": {
|
|
"type": "boolean",
|
|
"nullable": false,
|
|
"description": "Activation flag."
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Profile updated.",
|
|
"body": {
|
|
"$ref": "#/schemas/Profile"
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "No updatable fields provided or invalid data."
|
|
},
|
|
"401": {
|
|
"description": "Missing or invalid session."
|
|
},
|
|
"404": {
|
|
"description": "Profile not found."
|
|
},
|
|
"409": {
|
|
"description": "Constraint violation."
|
|
},
|
|
"503": {
|
|
"description": "Database unavailable."
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"operation_id": "deleteProfile",
|
|
"method": "DELETE",
|
|
"path": "/profiles/<profile_id>",
|
|
"authenticated": true,
|
|
"description": "Remove a profile by UUID.",
|
|
"request": {
|
|
"headers": {
|
|
"X-Session-Token": {
|
|
"type": "string",
|
|
"required": true,
|
|
"description": "Session token from /auth/login."
|
|
}
|
|
},
|
|
"path_params": [
|
|
{
|
|
"name": "profile_id",
|
|
"type": "uuid",
|
|
"required": true,
|
|
"description": "Profile identifier."
|
|
}
|
|
],
|
|
"body": null
|
|
},
|
|
"responses": {
|
|
"204": {
|
|
"description": "Profile deleted. Empty body."
|
|
},
|
|
"401": {
|
|
"description": "Missing or invalid session."
|
|
},
|
|
"404": {
|
|
"description": "Profile not found."
|
|
},
|
|
"503": {
|
|
"description": "Database unavailable."
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"operation_id": "listUsers",
|
|
"method": "GET",
|
|
"path": "/users",
|
|
"authenticated": true,
|
|
"description": "List all users ordered by ascending id.",
|
|
"request": {
|
|
"headers": {
|
|
"X-Session-Token": {
|
|
"type": "string",
|
|
"required": true,
|
|
"description": "Session token from /auth/login."
|
|
}
|
|
},
|
|
"body": null
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Array of users.",
|
|
"body": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/schemas/User"
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Missing or invalid session."
|
|
},
|
|
"503": {
|
|
"description": "Database unavailable."
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"operation_id": "getUser",
|
|
"method": "GET",
|
|
"path": "/users/<user_id>",
|
|
"authenticated": true,
|
|
"description": "Retrieve a user by numeric id.",
|
|
"request": {
|
|
"headers": {
|
|
"X-Session-Token": {
|
|
"type": "string",
|
|
"required": true,
|
|
"description": "Session token from /auth/login."
|
|
}
|
|
},
|
|
"path_params": [
|
|
{
|
|
"name": "user_id",
|
|
"type": "integer",
|
|
"required": true,
|
|
"description": "User primary key."
|
|
}
|
|
],
|
|
"body": null
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "User payload.",
|
|
"body": {
|
|
"$ref": "#/schemas/User"
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Missing or invalid session."
|
|
},
|
|
"404": {
|
|
"description": "User not found."
|
|
},
|
|
"503": {
|
|
"description": "Database unavailable."
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"operation_id": "createUser",
|
|
"method": "POST",
|
|
"path": "/users",
|
|
"authenticated": true,
|
|
"description": "Create a new user record.",
|
|
"request": {
|
|
"headers": {
|
|
"Content-Type": {
|
|
"type": "string",
|
|
"required": true,
|
|
"example": "application/json"
|
|
},
|
|
"X-Session-Token": {
|
|
"type": "string",
|
|
"required": true,
|
|
"description": "Session token from /auth/login."
|
|
}
|
|
},
|
|
"body": {
|
|
"type": "object",
|
|
"required_fields": [
|
|
"password",
|
|
"username",
|
|
"first_name",
|
|
"last_name",
|
|
"email"
|
|
],
|
|
"fields": {
|
|
"password": {
|
|
"type": "string",
|
|
"nullable": false,
|
|
"description": "Password to store. No hashing performed."
|
|
},
|
|
"username": {
|
|
"type": "string",
|
|
"nullable": false,
|
|
"description": "Unique username."
|
|
},
|
|
"first_name": {
|
|
"type": "string",
|
|
"nullable": false,
|
|
"description": "First name."
|
|
},
|
|
"last_name": {
|
|
"type": "string",
|
|
"nullable": false,
|
|
"description": "Last name."
|
|
},
|
|
"email": {
|
|
"type": "string",
|
|
"nullable": false,
|
|
"description": "Email address."
|
|
},
|
|
"is_superuser": {
|
|
"type": "boolean",
|
|
"nullable": false,
|
|
"description": "Defaults to false when omitted."
|
|
},
|
|
"is_staff": {
|
|
"type": "boolean",
|
|
"nullable": false,
|
|
"description": "Defaults to false when omitted."
|
|
},
|
|
"is_active": {
|
|
"type": "boolean",
|
|
"nullable": false,
|
|
"description": "Defaults to true when omitted."
|
|
},
|
|
"date_joined": {
|
|
"type": "datetime",
|
|
"nullable": true,
|
|
"description": "Optional. Defaults to current UTC when omitted or null."
|
|
},
|
|
"last_login": {
|
|
"type": "datetime",
|
|
"nullable": true,
|
|
"description": "Optional last login timestamp."
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"201": {
|
|
"description": "User created.",
|
|
"body": {
|
|
"$ref": "#/schemas/User"
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Validation failure."
|
|
},
|
|
"401": {
|
|
"description": "Missing or invalid session."
|
|
},
|
|
"409": {
|
|
"description": "Constraint violation (e.g., duplicate username or email)."
|
|
},
|
|
"503": {
|
|
"description": "Database unavailable."
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"operation_id": "updateUser",
|
|
"method": "PUT",
|
|
"path": "/users/<user_id>",
|
|
"authenticated": true,
|
|
"description": "Update mutable fields on a user.",
|
|
"request": {
|
|
"headers": {
|
|
"Content-Type": {
|
|
"type": "string",
|
|
"required": true,
|
|
"example": "application/json"
|
|
},
|
|
"X-Session-Token": {
|
|
"type": "string",
|
|
"required": true,
|
|
"description": "Session token from /auth/login."
|
|
}
|
|
},
|
|
"path_params": [
|
|
{
|
|
"name": "user_id",
|
|
"type": "integer",
|
|
"required": true,
|
|
"description": "User primary key."
|
|
}
|
|
],
|
|
"body": {
|
|
"type": "object",
|
|
"allowed_fields": [
|
|
"password",
|
|
"username",
|
|
"first_name",
|
|
"last_name",
|
|
"email",
|
|
"is_superuser",
|
|
"is_staff",
|
|
"is_active",
|
|
"date_joined",
|
|
"last_login"
|
|
],
|
|
"min_fields": 1,
|
|
"fields": {
|
|
"password": {
|
|
"type": "string",
|
|
"nullable": false,
|
|
"description": "New raw password."
|
|
},
|
|
"username": {
|
|
"type": "string",
|
|
"nullable": false,
|
|
"description": "New username."
|
|
},
|
|
"first_name": {
|
|
"type": "string",
|
|
"nullable": false,
|
|
"description": "New first name."
|
|
},
|
|
"last_name": {
|
|
"type": "string",
|
|
"nullable": false,
|
|
"description": "New last name."
|
|
},
|
|
"email": {
|
|
"type": "string",
|
|
"nullable": false,
|
|
"description": "New email."
|
|
},
|
|
"is_superuser": {
|
|
"type": "boolean",
|
|
"nullable": false,
|
|
"description": "Updated admin flag."
|
|
},
|
|
"is_staff": {
|
|
"type": "boolean",
|
|
"nullable": false,
|
|
"description": "Updated staff flag."
|
|
},
|
|
"is_active": {
|
|
"type": "boolean",
|
|
"nullable": false,
|
|
"description": "Updated active flag."
|
|
},
|
|
"date_joined": {
|
|
"type": "datetime",
|
|
"nullable": false,
|
|
"description": "Updated join timestamp."
|
|
},
|
|
"last_login": {
|
|
"type": "datetime",
|
|
"nullable": true,
|
|
"description": "Updated last login timestamp."
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "User updated.",
|
|
"body": {
|
|
"$ref": "#/schemas/User"
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "No updatable fields provided or invalid data."
|
|
},
|
|
"401": {
|
|
"description": "Missing or invalid session."
|
|
},
|
|
"404": {
|
|
"description": "User not found."
|
|
},
|
|
"409": {
|
|
"description": "Constraint violation."
|
|
},
|
|
"503": {
|
|
"description": "Database unavailable."
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"operation_id": "deleteUser",
|
|
"method": "DELETE",
|
|
"path": "/users/<user_id>",
|
|
"authenticated": true,
|
|
"description": "Delete a user by id.",
|
|
"request": {
|
|
"headers": {
|
|
"X-Session-Token": {
|
|
"type": "string",
|
|
"required": true,
|
|
"description": "Session token from /auth/login."
|
|
}
|
|
},
|
|
"path_params": [
|
|
{
|
|
"name": "user_id",
|
|
"type": "integer",
|
|
"required": true,
|
|
"description": "User primary key."
|
|
}
|
|
],
|
|
"body": null
|
|
},
|
|
"responses": {
|
|
"204": {
|
|
"description": "User deleted. Empty body."
|
|
},
|
|
"401": {
|
|
"description": "Missing or invalid session."
|
|
},
|
|
"404": {
|
|
"description": "User not found."
|
|
},
|
|
"503": {
|
|
"description": "Database unavailable."
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"operation_id": "listScrapers",
|
|
"method": "GET",
|
|
"path": "/scrapers",
|
|
"authenticated": true,
|
|
"description": "List all scraper configurations ordered by id.",
|
|
"request": {
|
|
"headers": {
|
|
"X-Session-Token": {
|
|
"type": "string",
|
|
"required": true,
|
|
"description": "Session token from /auth/login."
|
|
}
|
|
},
|
|
"body": null
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Array of scrapers.",
|
|
"body": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/schemas/Scraper"
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Missing or invalid session."
|
|
},
|
|
"503": {
|
|
"description": "Database unavailable."
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"operation_id": "getScraper",
|
|
"method": "GET",
|
|
"path": "/scrapers/<scraper_id>",
|
|
"authenticated": true,
|
|
"description": "Retrieve a single scraper by text id.",
|
|
"request": {
|
|
"headers": {
|
|
"X-Session-Token": {
|
|
"type": "string",
|
|
"required": true,
|
|
"description": "Session token from /auth/login."
|
|
}
|
|
},
|
|
"path_params": [
|
|
{
|
|
"name": "scraper_id",
|
|
"type": "string",
|
|
"required": true,
|
|
"description": "Scraper identifier."
|
|
}
|
|
],
|
|
"body": null
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Scraper payload.",
|
|
"body": {
|
|
"$ref": "#/schemas/Scraper"
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Missing or invalid session."
|
|
},
|
|
"404": {
|
|
"description": "Scraper not found."
|
|
},
|
|
"503": {
|
|
"description": "Database unavailable."
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"operation_id": "createScraper",
|
|
"method": "POST",
|
|
"path": "/scrapers",
|
|
"authenticated": true,
|
|
"description": "Create a scraper configuration.",
|
|
"request": {
|
|
"headers": {
|
|
"Content-Type": {
|
|
"type": "string",
|
|
"required": true,
|
|
"example": "application/json"
|
|
},
|
|
"X-Session-Token": {
|
|
"type": "string",
|
|
"required": true,
|
|
"description": "Session token from /auth/login."
|
|
}
|
|
},
|
|
"body": {
|
|
"type": "object",
|
|
"required_fields": ["id"],
|
|
"fields": {
|
|
"id": {
|
|
"type": "string",
|
|
"nullable": false,
|
|
"description": "Scraper primary key."
|
|
},
|
|
"params": {
|
|
"type": "string",
|
|
"nullable": true,
|
|
"description": "Serialized parameter payload."
|
|
},
|
|
"frequency": {
|
|
"type": "string",
|
|
"nullable": true,
|
|
"description": "Execution cadence descriptor."
|
|
},
|
|
"task_name": {
|
|
"type": "string",
|
|
"nullable": true,
|
|
"description": "Linked task name."
|
|
},
|
|
"property_types": {
|
|
"type": "string",
|
|
"nullable": true,
|
|
"description": "Comma-separated property types."
|
|
},
|
|
"last_seen_days": {
|
|
"type": "integer",
|
|
"nullable": true,
|
|
"description": "Days since listing last seen."
|
|
},
|
|
"first_seen_days": {
|
|
"type": "integer",
|
|
"nullable": true,
|
|
"description": "Days since listing first seen."
|
|
},
|
|
"page_size": {
|
|
"type": "integer",
|
|
"nullable": true,
|
|
"description": "Fetch size per page."
|
|
},
|
|
"max_pages": {
|
|
"type": "integer",
|
|
"nullable": true,
|
|
"description": "Maximum crawl pages."
|
|
},
|
|
"enabled": {
|
|
"type": "integer",
|
|
"nullable": true,
|
|
"description": "Activation flag (1 or 0)."
|
|
},
|
|
"enrich_llm": {
|
|
"type": "integer",
|
|
"nullable": true,
|
|
"description": "LLM enrichment toggle (1 or 0)."
|
|
},
|
|
"only_match": {
|
|
"type": "integer",
|
|
"nullable": true,
|
|
"description": "Strict matching toggle (1 or 0)."
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"201": {
|
|
"description": "Scraper created.",
|
|
"body": {
|
|
"$ref": "#/schemas/Scraper"
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Validation failure."
|
|
},
|
|
"401": {
|
|
"description": "Missing or invalid session."
|
|
},
|
|
"409": {
|
|
"description": "Constraint violation (e.g., duplicate id)."
|
|
},
|
|
"503": {
|
|
"description": "Database unavailable."
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"operation_id": "updateScraper",
|
|
"method": "PUT",
|
|
"path": "/scrapers/<scraper_id>",
|
|
"authenticated": true,
|
|
"description": "Update mutable fields on a scraper configuration.",
|
|
"request": {
|
|
"headers": {
|
|
"Content-Type": {
|
|
"type": "string",
|
|
"required": true,
|
|
"example": "application/json"
|
|
},
|
|
"X-Session-Token": {
|
|
"type": "string",
|
|
"required": true,
|
|
"description": "Session token from /auth/login."
|
|
}
|
|
},
|
|
"path_params": [
|
|
{
|
|
"name": "scraper_id",
|
|
"type": "string",
|
|
"required": true,
|
|
"description": "Scraper identifier."
|
|
}
|
|
],
|
|
"body": {
|
|
"type": "object",
|
|
"allowed_fields": [
|
|
"params",
|
|
"frequency",
|
|
"task_name",
|
|
"property_types",
|
|
"last_seen_days",
|
|
"first_seen_days",
|
|
"page_size",
|
|
"max_pages",
|
|
"enabled",
|
|
"enrich_llm",
|
|
"only_match"
|
|
],
|
|
"min_fields": 1,
|
|
"fields": {
|
|
"params": {
|
|
"type": "string",
|
|
"nullable": true,
|
|
"description": "Updated serialized parameters."
|
|
},
|
|
"frequency": {
|
|
"type": "string",
|
|
"nullable": true,
|
|
"description": "Updated cadence descriptor."
|
|
},
|
|
"task_name": {
|
|
"type": "string",
|
|
"nullable": true,
|
|
"description": "Updated task name."
|
|
},
|
|
"property_types": {
|
|
"type": "string",
|
|
"nullable": true,
|
|
"description": "Updated property type list."
|
|
},
|
|
"last_seen_days": {
|
|
"type": "integer",
|
|
"nullable": true,
|
|
"description": "Updated last seen days."
|
|
},
|
|
"first_seen_days": {
|
|
"type": "integer",
|
|
"nullable": true,
|
|
"description": "Updated first seen days."
|
|
},
|
|
"page_size": {
|
|
"type": "integer",
|
|
"nullable": true,
|
|
"description": "Updated page size."
|
|
},
|
|
"max_pages": {
|
|
"type": "integer",
|
|
"nullable": true,
|
|
"description": "Updated max pages."
|
|
},
|
|
"enabled": {
|
|
"type": "integer",
|
|
"nullable": true,
|
|
"description": "Updated enabled flag."
|
|
},
|
|
"enrich_llm": {
|
|
"type": "integer",
|
|
"nullable": true,
|
|
"description": "Updated enrichment flag."
|
|
},
|
|
"only_match": {
|
|
"type": "integer",
|
|
"nullable": true,
|
|
"description": "Updated only match flag."
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Scraper updated.",
|
|
"body": {
|
|
"$ref": "#/schemas/Scraper"
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "No updatable fields provided or invalid data."
|
|
},
|
|
"401": {
|
|
"description": "Missing or invalid session."
|
|
},
|
|
"404": {
|
|
"description": "Scraper not found."
|
|
},
|
|
"409": {
|
|
"description": "Constraint violation."
|
|
},
|
|
"503": {
|
|
"description": "Database unavailable."
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"operation_id": "deleteScraper",
|
|
"method": "DELETE",
|
|
"path": "/scrapers/<scraper_id>",
|
|
"authenticated": true,
|
|
"description": "Delete a scraper configuration.",
|
|
"request": {
|
|
"headers": {
|
|
"X-Session-Token": {
|
|
"type": "string",
|
|
"required": true,
|
|
"description": "Session token from /auth/login."
|
|
}
|
|
},
|
|
"path_params": [
|
|
{
|
|
"name": "scraper_id",
|
|
"type": "string",
|
|
"required": true,
|
|
"description": "Scraper identifier."
|
|
}
|
|
],
|
|
"body": null
|
|
},
|
|
"responses": {
|
|
"204": {
|
|
"description": "Scraper deleted. Empty body."
|
|
},
|
|
"401": {
|
|
"description": "Missing or invalid session."
|
|
},
|
|
"404": {
|
|
"description": "Scraper not found."
|
|
},
|
|
"503": {
|
|
"description": "Database unavailable."
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|