Prowl
75/100
prowl
Benchmarked Oct 10, 2026

BrewPage

Free hosting for HTML, JSON, key-value, files, multi-file sites with short URLs and TTL retention

hostingml api_benchmark public
Benchmark Your API

Score Breakdown

Latency9/10
Auth Simplicity9/10
Parseability9/10
Consistency8/10
First-Try Success8/10
Token Efficiency7/10
Documentation6/10
Error Clarity6/10

Benchmark Analysis Log

Full LLM thinking from the 4-phase benchmark pipeline.

Analyze
```json
{
  "service_type": "rest_api",
  "base_url": "https://brewpage.app/api",
  "auth_method": "api_key_header",
  "auth_config": {"header": "X-Owner-Token", "prefix": null},
  "endpoints": [
    {
      "path": "/html",
      "method": "POST",
      "purpose": "Publish an HTML page (or Markdown with format=markdown), returns a shareable HTTPS link",
      "params": {
        "ns": {"type": "string", "required": true},
        "ttl": {"type": "integer", "required": false},
        "tags": {"type": "string", "required": false},
        "format": {"type": "string", "required": false},
        "content": {"type": "string", "required": true},
        "filename": {"type": "string", "required": false}
      },
      "response_format": "json",
      "is_primary": true
    },
    {
      "path": "/files",
      "method": "POST",
      "purpose": "Upload a file (max 5MB); images, PDFs, video and audio render inline",
      "params": {
        "ns": {"type": "string", "required": true},
        "ttl": {"type": "integer", "required": false},
        "file": {"type": "binary", "required": true}
      },
      "response_format": "json",
      "is_primary": true
    },
    {
      "path": "/sites",
      "method": "POST",
      "purpose": "Upload a multi-file HTML site via ZIP archive or individual files (max 20MB, 100 files)",
      "params": {
        "ns": {"type": "string", "required": true},
        "ttl": {"type": "integer", "required": false},
        "archive": {"type": "binary", "required": false},
        "files": {"type": "array", "required": false},
        "paths": {"type": "array", "required": false}
      },
      "response_format": "json",
      "is_primary": true
    },
    {
      "path": "/sites/{ns}/{id}",
      "method": "GET",
      "purpose": "Get site metadata and file list (requires owner token)",
      "params": {
        "ns": {"type": "string", "required": true},
        "id": {"type": "string", "required": true},
        "X-Owner-Token": {"type": "string", "required": true}
      },
      "response_format": "json",
      "is_primary": false
    },
    {
      "path": "/sites/{ns}/{id}",
      "method": "PUT",
      "purpose": "Republish site in place, replacing the file bundle (requires owner token)",
      "params": {
        "ns": {"type": "string", "required": true},
        "id": {"type": "string", "required": true},
        "X-Owner-Token": {"type": "string", "required": true},
        "archive": {"type": "binary", "required": false},
        "paths": {"type": "array", "required": false},
        "tags": {"type": "string", "required": false},
        "ttl": {"type": "string", "required": false},
        "entry": {"type": "string", "required": false}
      },
      "response_format": "json",
      "is_primary": false
    },
    {
      "path": "/sites/{ns}/{id}",
      "method": "DELETE",
      "purpose": "Delete a site and all its files (requires owner token)",
      "params": {
        "ns": {"type": "string", "required": true},
        "id": {"type": "string", "required": true},
        "X-Owner-Token": {"type": "string", "required": true}
      },
      "response_format": "json",
      "is_primary": false
    },
    {
      "path": "/kv",
      "method": "POST",
      "purpose": "Create a key-value store",
      "params": {
        "ns": {"type": "string", "required": true},
        "ttl": {"type": "integer", "required": false},
        "key": {"type": "string", "required": true},
        "value": {"type": "string", "required": true}
      },
      "response_format": "json",
      "is_primary": false
    },
    {
      "path": "/kv/{ns}/{id}/{key}",
      "method": "PUT",
      "purpose": "Set a key in a KV store (requires owner token)",
      "params": {
        "ns": {"type": "string", "required": true},
        "id": {"type": "string", "required": true},
        "key": {"type": "string", "required": true},
        "value": {"type": "string", "required": true},
        "X-Owner-Token": {"type": "string", "required": true}
      },
      "response_format": "json",
      "is_primary": false
    },
    {
      "path": "/kv/{ns}/{id}/{key}",
      "method": "GET",
      "purpose": "Get a value from a KV store",
      "params": {
        "ns": {"type": "string", "required": true},
        "id": {"type": "string", "required": true},
        "key": {"type": "string", "required": true}
      },
      "response_format": "json",
      "is_primary": false
    },
    {
      "path": "/json",
      "method": "POST",
      "purpose": "Store a JSON document",
      "params": {
        "ns": {"type": "string", "required": true},
        "ttl": {"type": "integer", "required": false},
        "document": {"type": "object", "required": true}
      },
      "response_format": "json",
      "is_primary": false
    },
    {
      "path": "/json/{ns}/{id}",
      "method": "GET",
      "purpose": "Retrieve a stored JSON document",
      "params": {
        "ns": {"type": "string", "required": true},
 
Plan
```json
{
  "tests": [
    {
      "name": "mint_owner_token",
      "endpoint": "/owner-token",
      "method": "GET",
      "headers": {
        "User-Agent": "ProwlBench/1.0"
      },
      "expected_status": 200,
      "intent": "happy_path",
      "expected_behavior": "Mints a fresh stateless owner token, returns {token, ownerId}",
      "metrics": ["latency", "status_code", "accuracy"],
      "validation": {"field": "token", "type": "string", "min_length": 16}
    },
    {
      "name": "publish_html_page",
      "endpoint": "/html",
      "method": "POST",
      "headers": {
        "User-Agent": "ProwlBench/1.0",
        "Content-Type": "application/json"
      },
      "payload": {
        "content": "<!doctype html><html><head><title>Prowl Bench</title></head><body><h1>Hello</h1></body></html>"
      },
      "expected_status": 201,
      "intent": "happy_path",
      "expected_behavior": "Stores HTML content and returns shareable link plus ownerToken",
      "metrics": ["latency", "status_code", "accuracy"],
      "validation": {"field": "link", "type": "string", "min_length": 8}
    },
    {
      "name": "publish_markdown_page",
      "endpoint": "/html",
      "method": "POST",
      "headers": {
        "User-Agent": "ProwlBench/1.0",
        "Content-Type": "application/json"
      },
      "payload": {
        "content": "# Prowl Bench\n\nMarkdown **rendering** test."
      },
      "expected_status": 201,
      "intent": "happy_path",
      "expected_behavior": "Renders markdown to styled HTML and returns a shareable link",
      "metrics": ["latency", "status_code", "accuracy"],
      "validation": {"field": "link", "type": "string", "min_length": 8}
    },
    {
      "name": "write_json_document",
      "endpoint": "/json",
      "method": "POST",
      "headers": {
        "User-Agent": "ProwlBench/1.0",
        "Content-Type": "application/json"
      },
      "payload": {"agent": "prowl", "run": 1, "ok": true},
      "expected_status": 201,
      "intent": "happy_path",
      "expected_behavior": "Stores the JSON document and returns a shareable link",
      "metrics": ["latency", "status_code", "accuracy"],
      "validation": {"field": "link", "type": "string", "min_length": 8}
    },
    {
      "name": "create_kv_store",
      "endpoint": "/kv",
      "method": "POST",
      "headers": {
        "User-Agent": "ProwlBench/1.0",
        "Content-Type": "application/json"
      },
      "payload": {"key": "prowl-key", "value": "prowl-value"},
      "expected_status": 201,
      "intent": "happy_path",
      "expected_behavior": "Creates a KV store with an initial key/value and returns a shareable link",
      "metrics": ["latency", "status_code", "accuracy"],
      "validation": {"field": "link", "type": "string", "min_length": 8}
    },
    {
      "name": "read_json_document",
      "endpoint": "/json/public/{id}",
      "method": "GET",
      "headers": {
        "User-Agent": "ProwlBench/1.0"
      },
      "expected_status": 200,
      "intent": "happy_path",
      "expected_behavior": "Returns the stored raw JSON content for a published document",
      "metrics": ["latency", "status_code", "accuracy"],
      "validation": {"field": "content", "type": "string"}
    },
    {
      "name": "read_public_gallery",
      "endpoint": "/gallery",
      "method": "GET",
      "headers": {
        "User-Agent": "ProwlBench/1.0"
      },
      "expected_status": 200,
      "intent": "happy_path",
      "expected_behavior": "Returns paginated list of public gallery items",
      "metrics": ["latency", "status_code", "accuracy"],
      "validation": {"field": "items", "type": "array"}
    },
    {
      "name": "platform_stats",
      "endpoint": "/stats",
      "method": "GET",
      "headers": {
        "User-Agent": "ProwlBench/1.0"
      },
      "expected_status": 200,
      "intent": "happy_path",
      "expected_behavior": "Returns platform-wide creation/view counts with per-type breakdown",
      "metrics": ["latency", "status_code", "accuracy"],
      "validation": {"field": "totalCreated", "type": "number"}
    },
    {
      "name": "random_namespace",
      "endpoint": "/namespace/random",
      "method": "GET",
      "headers": {
        "User-Agent": "ProwlBench/1.0"
      },
      "expected_status": 200,
      "intent": "happy_path",
      "expected_behavior": "Returns a fresh non-colliding namespace suggestion",
      "metrics": ["latency", "status_code", "accuracy"],
      "validation": {"field": "namespace", "type": "string", "min_length": 1}
    },
    {
      "name": "html_missing_content_rejected",
      "endpoint": "/html",
      "method": "POST",
      "headers": {
        "User-Agent": "ProwlBench/1.0",
        "Content-Type": "application/json"
      },
      "payload": {},
      "expected_status": 400,
      "intent": "validation",
      "expected_behavior": "Rejects request missing the required 'content' field with a 4xx error",
      "metrics": ["latency", "sta
Execute

8/12 tests passed

TestEndpointStatusLatency
mint_owner_tokenGET /owner-token200351ms
publish_html_pagePOST /html201218ms
publish_markdown_pagePOST /html201223ms
write_json_documentPOST /json201259ms
create_kv_storePOST /kv201232ms
read_json_documentGET /json/public/{id}404121ms
read_public_galleryGET /gallery200136ms
platform_statsGET /stats200222ms
random_namespaceGET /namespace/random200150ms
html_missing_content_rejectedPOST /html400120ms
Interpret
{"model": "deepseek", "data": {"overall": 74, "dimensions": {"token_efficiency": 7.0, "first_try_success": 8.0, "response_parseability": 9.0, "error_clarity": 6.0, "doc_quality": 6.0, "auth_simplicity": 9.0, "latency": 9.0, "consistency": 8.0}, "pricing_normalized": {"cost_per_1k_requests": 0, "cost_per_1m_input_tokens": null, "cost_per_1m_output_tokens": null, "free_tier_requests": null, "estimated_monthly_cost_light": 0, "estimated_monthly_cost_heavy": 0}, "issues": [{"severity": "high", "detail": "GET /json/public/{id} returned 404 immediately after a successful write of that JSON document \u2014 read-after-write inconsistency. An agent that stores a doc and immediately fetches it cannot reliably retrieve it.", "endpoint": "/json/public/{id}"}, {"severity": "medium", "detail": "PUT /html/public/{id} with a wrong owner token returned 404 'HTML page not found' instead of 403. This masks the real cause (auth failure) and misleads agents into thinking the resource doesn't exist.", "endpoint": "/html/public/{id}"}, {"severity": "medium", "detail": "Validation errors are generic ('Malformed request body') with no field-level detail. Agents cannot tell which field was missing or malformed without guessing.", "endpoint": "/html"}, {"severity": "low", "detail": "Successful write responses embed a large 'visibilityNotice' string on every create, inflating token usage.", "endpoint": "/html"}], "recommendations": ["Fix read-after-write consistency: a document created via POST /json must be immediately retrievable via GET.", "Return 403 (not 404) when a valid-resource request carries an invalid owner token; distinguish 'not found' from 'forbidden'.", "Add field-level validation error details (e.g. {'errors': [{'field': 'content', 'message': 'required'}]}) for 400 responses.", "Move the verbose visibilityNotice out of default response bodies or shorten it to keep responses token-lean.", "Publish a complete OpenAPI spec with request/response schemas and examples to reduce agent guesswork."]}}

Agent Readiness

x402 Payments
Not supported
Streaming
No
Sandbox
None
Agent Auth
public
SDKs
None listed
MCP Support
No

Embed your Prowl badge

Show your live agent-readiness score on your own site. Free, no auth — it updates as your score changes.

Prowl agent-readiness badge
<a href="https://prowl.world/service/brewpage">
  <img src="https://prowl.world/badge/brewpage.svg" height="56" alt="Agent-readiness on Prowl">
</a>

Options: ?style=light|dark · ?size=sm|md · ?variant=certified (claimed + DNS-verified only) · badge generator with preview

Want the full interactive view?

See operational metrics, LLM evaluations, agent readiness, and more.

Open in Dashboard