DevPlace REST: SEO Diagnostics, DeepSearch and AI Usage Analyzer
Background-job endpoints for the three public developer tools: queueing a run, polling status, reading the report, and the progress websockets - all addressed by unguessable capability URLs.
Two public developer tools that run as background jobs.
SEO Diagnostics audits a URL or sitemap with a headless browser and runs a broad battery of technical, on-page, structured-data, Core Web Vitals, accessibility and AI-readiness checks.
DeepSearch is a multi-agent deep web researcher that crawls and indexes sources, then synthesises a cited report with confidence scoring and gap analysis, plus a grounded chat over the results.
AI Usage Analyzer classifies a git repository or website as AI slop, sophisticated AI-assisted work or genuine human work, and publishes a persistent report with an embeddable authenticity badge.
Every endpoint follows the shared Conventions & Errors. These are capability URLs: the job uid is an unguessable identifier, so anyone holding it can read the status and report.
POST /tools/seo/run - Queue an SEO audit
Start a background SEO audit of a URL or sitemap. Returns the job uid plus status and websocket URLs.
Minimal role: Public
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
url | form | string | yes | Page URL or sitemap.xml URL to audit. |
mode | form | enum | no | 'url' (single page) or 'sitemap' (crawl). Allowed: url, sitemap. |
max_pages | form | integer | no | Max pages to crawl in sitemap mode (1-50). |
Sample response
{
"uid": "SEO_JOB_UID",
"status_url": "/tools/seo/SEO_JOB_UID",
"ws_url": "/tools/seo/SEO_JOB_UID/ws"
}
GET /tools/seo/{uid} - SEO audit status
Poll an SEO audit. Once done, score, grade and report_url are populated.
Minimal role: Public
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
uid | path | string | yes | SEO job uid returned when the audit was queued. |
Sample response
{
"uid": "SEO_JOB_UID",
"kind": "seo",
"status": "done",
"target": "https://example.com",
"mode": "url",
"ws_url": "/tools/seo/SEO_JOB_UID/ws",
"report_url": "/tools/seo/SEO_JOB_UID/report",
"score": 82,
"grade": "B",
"page_count": 1,
"error": null,
"created_at": "2026-06-14T10:00:00+00:00",
"completed_at": "2026-06-14T10:00:18+00:00"
}
GET /tools/seo/{uid}/report - SEO audit report
Full categorised report: overall score, per-category subscores, and every check with its recommendation. Negotiates HTML or JSON.
Minimal role: Public
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
uid | path | string | yes | SEO job uid of a finished audit. |
Sample response
{
"uid": "SEO_JOB_UID",
"status": "done",
"target": "https://example.com",
"score": 82,
"grade": "B",
"page_count": 1,
"counts": {
"pass": 40,
"warn": 8,
"fail": 3,
"info": 5,
"skip": 0
},
"categories": {
"crawlability": {
"score": 90,
"pass": 9,
"warn": 1,
"fail": 0
}
},
"pages": [
{
"url": "https://example.com",
"status": 200,
"score": 82,
"grade": "B"
}
],
"checks": [
{
"id": "meta.title_present",
"category": "meta",
"title": "Title tag",
"status": "pass",
"severity": "high",
"value": "Example Domain",
"recommendation": "",
"url": "https://example.com"
}
],
"site": {
"robots": {
"status": 200
},
"sitemap": {
"status": 200,
"url_count": 12
}
},
"generated_at": "2026-06-14T10:00:18+00:00"
}
GET /tools/seo/{uid}/screenshot/{index} - SEO audit page screenshot
Stream the rendered screenshot (image/png) captured for the audited page at the given zero-based index.
Minimal role: Public
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
uid | path | string | yes | SEO job uid of a finished audit. |
index | path | integer | yes | Zero-based index of the audited page. |
GET /tools/seo-meta/{targettype}/{targetuid} - Generated SEO metadata for a content item
Read the clean, AI-generated SEO title, description and keywords for a published post, project, gist, news article or issue. Returns a plain-content default with status 'pending' until the AI value is ready.
Minimal role: Public
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
target_type | path | enum | yes | Content type. Allowed: post, project, gist, news, issue. |
target_uid | path | string | yes | The content uid (or issue number). |
Sample response
{
"uid": "SEO_META_UID",
"target_type": "post",
"target_uid": "CONTENT_UID",
"seo_title": "Building a fast SQLite social network",
"seo_description": "How DevPlace keeps SQLite synchronous and still serves a developer social network fast, with WAL, mmap and batch query helpers.",
"seo_keywords": "sqlite, fastapi, social network, performance, wal",
"status": "ready",
"source": "ai",
"generated_at": "2026-06-14T10:00:18+00:00"
}
POST /tools/deepsearch/run - Queue a DeepSearch research job
Start a multi-agent deep web research job. Returns the job uid plus status and websocket URLs. Connect ws_url for live progress frames.
Minimal role: Public
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
query | form | string | yes | The research question to investigate. |
depth | form | integer | no | Research depth (1-4). |
max_pages | form | integer | no | Maximum sources to crawl (1-30). |
Sample response
{
"uid": "DEEPSEARCH_JOB_UID",
"status_url": "/tools/deepsearch/DEEPSEARCH_JOB_UID",
"ws_url": "/tools/deepsearch/DEEPSEARCH_JOB_UID/ws",
"progress_frames_note": "The ws_url stream emits newline-delimited JSON frames; the set is append-only and the first frame carries version:1. Each frame has a type: phase (phase, index, total, label), stage, substep (planning angles), queries, candidates, rsearch, progress (done, total, url), page_loaded (source, render, elapsed_ms, done, total), page_cached, page_skipped (reason), page_duplicate, embed_batch (batch, total_batches, backend, done, total), embed_done (backend, chunk_count), agent (agent, status start|done, elapsed_ms, tokens_in, tokens_out), report_ready, done (session_url), failed (message)."
}
GET /tools/deepsearch/{uid} - DeepSearch status
Poll a DeepSearch job. Once done, score, confidence and session_url are populated.
Minimal role: Public
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
uid | path | string | yes | DeepSearch job uid returned when the run was queued. |
Sample response
{
"uid": "DEEPSEARCH_JOB_UID",
"kind": "deepsearch",
"status": "done",
"query": "history of the transistor",
"depth": 2,
"max_pages": 12,
"ws_url": "/tools/deepsearch/DEEPSEARCH_JOB_UID/ws",
"chat_ws_url": "/tools/deepsearch/DEEPSEARCH_JOB_UID/chat",
"session_url": "/tools/deepsearch/DEEPSEARCH_JOB_UID/session",
"score": 78,
"confidence": 0.72,
"source_diversity": 0.64,
"page_count": 11,
"chunk_count": 240,
"error": null,
"created_at": "2026-06-14T10:00:00+00:00",
"completed_at": "2026-06-14T10:01:40+00:00"
}
GET /tools/deepsearch/{uid}/session - DeepSearch report
Full cited research report: summary, findings, sources and metrics. Negotiates HTML or JSON.
Minimal role: Public
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
uid | path | string | yes | DeepSearch job uid of a finished run. |
Sample response
{
"uid": "DEEPSEARCH_JOB_UID",
"status": "done",
"query": "history of the transistor",
"score": 78,
"confidence": 0.72,
"source_diversity": 0.64,
"page_count": 11,
"chunk_count": 240,
"summary": "The transistor was invented at Bell Labs in 1947...",
"findings": [
{
"title": "Invention",
"detail": "...",
"confidence": 0.8,
"citations": [
1
]
}
],
"sources": [
{
"url": "https://example.com",
"title": "Example",
"source": "httpx"
}
],
"chat_ws_url": "/tools/deepsearch/DEEPSEARCH_JOB_UID/chat",
"export_md_url": "/tools/deepsearch/DEEPSEARCH_JOB_UID/export.md",
"export_json_url": "/tools/deepsearch/DEEPSEARCH_JOB_UID/export.json",
"export_pdf_url": "/tools/deepsearch/DEEPSEARCH_JOB_UID/export.pdf"
}
POST /tools/isslop/run - Queue a AI usage analysis
Start a background authenticity analysis of a git repository or website. Returns the job uid plus status, events and report URLs.
Minimal role: Public
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
url | form | string | yes | Repository (http/git/ssh) or website URL to classify. |
Sample response
{
"uid": "ISSLOP_UID",
"status_url": "/tools/isslop/ISSLOP_UID",
"events_url": "/tools/isslop/ISSLOP_UID/events",
"report_url": "/tools/isslop/ISSLOP_UID/report",
"topic": "public.isslop.ISSLOP_UID"
}
GET /tools/isslop/list - My AI usage analyses
List the caller's analyses, newest first. Member history is account-bound; guest history is session-bound and claimed by the account on first signed-in call.
Minimal role: Public
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
limit | query | integer | no | Maximum analyses to return (1-200). |
Sample response
{
"analyses": [
{
"uid": "ISSLOP_UID",
"status": "completed",
"source_url": "https://github.com/owner/repository",
"source_kind": "git",
"grade": "B",
"human_percent": 71.4,
"ai_percent": 28.6,
"category": "human-clean",
"report_url": "/tools/isslop/ISSLOP_UID/report",
"badge_url": "/tools/isslop/ISSLOP_UID/badge.svg"
}
]
}
GET /tools/isslop/{uid} - AI usage analysis status
Poll an analysis. Once completed, grade, category and the human/AI split are populated.
Minimal role: Public
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
uid | path | string | yes | Analysis uid returned when the run was queued. |
Sample response
{
"uid": "ISSLOP_UID",
"status": "completed",
"source_url": "https://github.com/owner/repository",
"source_kind": "git",
"grade": "B",
"slop_score": 31.2,
"origin_score": 28.0,
"quality_deficit_score": 22.5,
"human_percent": 71.4,
"ai_percent": 28.6,
"category": "human-clean",
"confidence": "medium",
"files_total": 120,
"files_analyzed": 96,
"report_url": "/tools/isslop/ISSLOP_UID/report",
"badge_url": "/tools/isslop/ISSLOP_UID/badge.svg",
"events_url": "/tools/isslop/ISSLOP_UID/events",
"topic": "public.isslop.ISSLOP_UID"
}
GET /tools/isslop/{uid}/events - AI usage analysis event trail
The persisted, ordered event trail of an analysis. Use ?after=SEQ to poll incrementally; live frames also stream on the pub/sub topic.
Minimal role: Public
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
uid | path | string | yes | Analysis uid. |
after | query | integer | no | Return only events with a sequence number greater than this. |
limit | query | integer | no | Maximum events to return (1-5000). |
Sample response
{
"uid": "ISSLOP_UID",
"status": "running",
"events": [
{
"seq": 1,
"kind": "stage",
"message": "Resolving source type",
"data": {
"stage": "resolve"
},
"created_at": "2026-06-14T10:00:00+00:00"
}
]
}
GET /tools/isslop/{uid}/report - AI usage analysis report
Full report: verdict, markdown body, per-file results, image review and badge embeds. Negotiates HTML or JSON.
Minimal role: Public
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
uid | path | string | yes | Analysis uid of a finished run. |
Sample response
{
"uid": "ISSLOP_UID",
"status": "completed",
"source_url": "https://github.com/owner/repository",
"grade": "B",
"human_percent": 71.4,
"ai_percent": 28.6,
"category": "human-clean",
"markdown": "# Verdict...",
"generator_model": "molodetz",
"badge": {
"badge_url": "https://devplace.example/tools/isslop/ISSLOP_UID/badge.svg",
"report_url": "https://devplace.example/tools/isslop/ISSLOP_UID/report",
"markdown": "[](...)",
"html": "<a href=...><img src=.../></a>"
},
"files": [
{
"path": "src/main.py",
"language": "python",
"lines": 120,
"origin_score": 35.0,
"quality_deficit_score": 18.0,
"category": "human-clean",
"signals": []
}
],
"images": [
{
"path": "assets/hero.png",
"ai_probability": 84.0,
"grade": "F",
"verdict": "ai-generated",
"image_kind": "illustration",
"tells": [
"waxy skin"
],
"description": "...",
"thumb_url": "/tools/isslop/ISSLOP_UID/media/0f3a9c2d1b4e5a67.webp"
}
]
}
GET /tools/isslop/{uid}/report.md - Download report markdown
Download the full report as a markdown file.
Minimal role: Public
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
uid | path | string | yes | Analysis uid of a finished run. |
GET /tools/isslop/{uid}/source - Annotated source of a flagged file
The persisted source of a signal-bearing file with its signals, rendered with line numbers and highlighted findings (HTML) or as JSON. Linked from the report's file table, signal chips and prose.
Minimal role: Public
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
uid | path | string | yes | Analysis uid. |
path | query | string | yes | Workspace-relative file path from the report. |
line | query | integer | no | Line to focus and highlight. |
Sample response
{
"uid": "ISSLOP_UID",
"path": "src/libs/Env.ts",
"language": "typescript",
"category": "human-clean",
"origin_score": 24.0,
"quality_deficit_score": 34.9,
"source": "import { createEnv } from '@t3-oss/env-nextjs';...",
"truncated": false,
"signals": [
{
"code": "PUBLIC_ENV_SECRET",
"title": "Secret exposed via public env variable",
"severity": "strong",
"line": 12
}
]
}
GET /tools/isslop/{uid}/media/{name} - Reviewed image thumbnail
Aspect-preserving WebP thumbnail of a reviewed image, persisted as evidence. The name comes from the report's images[].thumb_url.
Minimal role: Public
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
uid | path | string | yes | Analysis uid. |
name | path | string | yes | Thumbnail file name from the report. |
GET /tools/isslop/{uid}/badge.svg - Authenticity badge
Embeddable SVG badge showing the human score and authenticity grade, linking to the report.
Minimal role: Public
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
uid | path | string | yes | Analysis uid. |