HTTP API
Build on the PluginView scan API
Authenticate, submit URLs, and receive structured detection results. This reference covers endpoints, credits, errors, rate limits, and plan quotas.
Overview
PluginView exposes a small HTTP API under /api. There is no separate versioned path — the routes below are the live contract.
- Single scan — synchronous. Returns a full result payload when the scan finishes.
- Bulk job — asynchronous. Submit many URLs, receive a job id, and poll until each domain finishes.
Detection uses publicly reachable signals only — headers, cookies, HTML, scripts, and related metadata. It does not bypass logins, CAPTCHAs, or paywalls. Fingerprint rules are proprietary; responses include confidence scores and text explanations, not raw patterns. See methodology.
Quick start
Organization API keys require Developer or higher. Create a key in the dashboard, then:
curl -sS -X POST https://www.pluginview.com/api/scan \
-H "Authorization: Bearer pv_live_…" \
-H "Content-Type: application/json" \
-d '{"url":"https://shopify.com"}'The same endpoints power the website UI. Bulk jobs currently require a session cookie; see Authentication.
Authentication
Two auth modes are supported. Pick one per request.
- API key
Authorization: Bearer pv_live_…Organization-scoped. Requires a plan with API access (Developer and above). Preferred for servers and CI.- Session cookie
pv_sessionSet afterPOST /api/authwith{ "action": "login", … }. Used by the website UI. Bulk jobs currently require a session (not an API key).
Raw API keys are shown once at creation and never stored in plaintext. Rotate a key from the dashboard if it leaks. Keys cannot be shared across organizations.
Credits & scan modes
Every successful non-cached scan spends credits from the organization's balance. Cached replays and failed non-chargeable attempts cost nothing.
| Mode | Credits | What it adds |
|---|---|---|
static | 1 | Headers, cookies, HTML, scripts, meta, visible text |
dynamic | 5 | Browser rendering / JS runtime signals (plan-gated) |
extended | 8 | Dynamic plus DNS / TLS probes (Growth and above) |
If a deeper stage does not complete, you are only charged for the stages that did. Monthly included credits refresh with the plan; prepaid packs and overages (where enabled) top up the same ledger.
Single scan
/api/scanRun a synchronous technology scan. Auth via session cookie or Bearer pv_live_….
Request body
{
"url": "https://shopify.com",
"force": false
}url— required. Domain or full URL, max 2048 characters.force— optional. Bypass the success cache whentrue.mode— optional hint (static/dynamic/extended). Effective depth is still gated by plan and environment flags.
Success response
{
"id": "scan_…",
"inputUrl": "https://shopify.com",
"normalizedUrl": "https://shopify.com/",
"finalUrl": "https://www.shopify.com/",
"hostname": "www.shopify.com",
"statusCode": 200,
"scannedAt": "2026-07-30T20:00:00.000Z",
"durationMs": 842,
"cached": false,
"mode": "static",
"detections": [
{
"name": "Shopify",
"slug": "shopify",
"categories": ["Ecommerce"],
"confidence": 100,
"implied": false,
"evidence": [
{
"signal": "headers",
"summary": "A response header matched a known Shopify signature.",
"confidence": 100
}
]
}
],
"coverage": {
"mode": "static",
"headers": true,
"cookies": true,
"html": true,
"scripts": true,
"meta": true,
"text": true,
"jsRuntime": false,
"dom": false,
"dns": false,
"tls": false,
"notes": []
}
}Each detection includes a confidence score and a text explanation of the signal class involved. Fingerprint patterns are not returned. Treat confidence as a strength score, not a guarantee of a sitewide install.
/api/scan/:idFetch a previously produced scan by id. No auth required if you already hold the id — treat ids as unguessable secrets and do not publish them.
curl -sS https://www.pluginview.com/api/scan/scan_…Bulk jobs
/api/bulkQueue many domains for asynchronous scanning. Returns 202 Accepted with a job summary. Currently requires a signed-in session (browser cookie) — API-key bulk is not enabled yet.
curl -sS -X POST https://www.pluginview.com/api/bulk \
-H "Content-Type: application/json" \
-H "Cookie: pv_session=…" \
-d '{"urls":["shop.example.com","pay.example.com"]}'{
"id": "bulk_…",
"status": "queued",
"total": 2,
"completed": 0,
"failed": 0,
"createdAt": "2026-07-30T20:00:00.000Z",
"updatedAt": "2026-07-30T20:00:00.000Z",
"results": [
{ "url": "shop.example.com", "status": "pending" },
{ "url": "pay.example.com", "status": "pending" }
]
}urls— 1…N strings. Duplicates are collapsed. Per-plan caps apply (see Limits).- Free accounts cannot create bulk jobs when credits enforcement is on — upgrade to Developer or higher.
- Each completed URL still spends credits like an individual scan.
/api/bulk/:idPoll job progress. status moves through queued, running, then completed, partial, or failed. Per-URL rows expose scanId when finished so you can load the full result from GET /api/scan/:id.
Errors
Failures use a consistent envelope. HTTP status mirrors the code family (400, 401, 403, 404, 429).
{
"error": {
"code": "RATE_LIMITED",
"message": "You have reached the temporary free scan limit. …",
"details": { "resetAt": "…" },
"nextActions": [
{ "href": "/pricing", "label": "Upgrade plan" }
]
}
}| Code | Meaning |
|---|---|
BAD_REQUEST | Malformed body or invalid URL input |
INVALID_API_KEY | Bearer token missing, revoked, or malformed |
PLAN_REQUIRED | Feature needs a higher plan (API keys, bulk, deeper modes) |
INSUFFICIENT_CREDITS | Organization credit balance cannot cover the scan |
CONCURRENCY_LIMIT | All concurrent slots in use; request may be queued |
QUEUE_LIMIT | Queued-scan depth for the plan is full |
RATE_LIMITED | Hourly or daily request cap hit |
BULK_LIMIT | Too many URLs for the caller’s bulk allowance |
SUBSCRIPTION_INACTIVE | Paid subscription past grace — update billing |
NOT_FOUND | Unknown scan or bulk job id |
PRIVATE_ADDRESS / BLOCKED_* | Target refused for safety (SSRFs, ports) |
Limits & pricing
Quotas stack: request rate limits protect the edge, plan credits and concurrency gate sustained volume, and bulk caps bound a single job.
Request rate limits
Applied separately to single scans and bulk submissions. Registered accounts share the higher bucket whether they call via cookie or API key.
| Caller | Per hour | Per day |
|---|---|---|
| Anonymous (IP) | 5 | 10 |
| Registered / API key | 60 | 300 |
Pricing & individual capacity
Monthly credits and concurrency gate how many scans you can run. Each completed URL in a bulk job spends credits like an individual scan.
| Plan | Price | Credits / mo | Concurrent | API |
|---|---|---|---|---|
| Free | Free | 100 | 1 | — |
| Developer | $12/mo | 1,000 | 3 | Yes |
| Growth | $39/mo | 5,000 | 10 | Yes |
| Scale | $99/mo | 20,000 | 25 | Yes |
| Enterprise | $249/mo | 75,000 | 50 | Yes |
Bulk job size
Maximum URLs in a single bulk request. Enterprise is negotiated. Free requires an upgrade when credits enforcement is on.
| Plan | URLs / job |
|---|---|
| Anonymous | 5 URLs |
| Free | Upgrade required |
| Developer | 100 URLs |
| Growth | 500 URLs |
| Scale | 2,500 URLs |
| Enterprise | Custom |
Deeper scan modes, scheduled jobs, team seats, and overage pricing also differ by plan — see the full pricing page.
Next steps
- Create an account for history and the registered rate bucket.
- Upgrade to Developer for API keys and bulk jobs.
- Create a key under Dashboard → API keys.
Enterprise capacity or a custom bulk ceiling: hello@pluginview.com.