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.

01

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.

02

Quick start

Organization API keys require Developer or higher. Create a key in the dashboard, then:

bash
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.

03

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 after POST /api/auth with { "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.

04

Credits & scan modes

Every successful non-cached scan spends credits from the organization's balance. Cached replays and failed non-chargeable attempts cost nothing.

ModeCreditsWhat it adds
static1Headers, cookies, HTML, scripts, meta, visible text
dynamic5Browser rendering / JS runtime signals (plan-gated)
extended8Dynamic 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.

05

Single scan

POST/api/scan

Run 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 when true.
  • mode — optional hint (static / dynamic / extended). Effective depth is still gated by plan and environment flags.

Success response

200 application/json
{
  "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.

GET/api/scan/:id

Fetch 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.

bash
curl -sS https://www.pluginview.com/api/scan/scan_…
06

Bulk jobs

POST/api/bulk

Queue 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.

bash
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"]}'
202 application/json
{
  "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.
GET/api/bulk/:id

Poll 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.

07

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" }
    ]
  }
}
CodeMeaning
BAD_REQUESTMalformed body or invalid URL input
INVALID_API_KEYBearer token missing, revoked, or malformed
PLAN_REQUIREDFeature needs a higher plan (API keys, bulk, deeper modes)
INSUFFICIENT_CREDITSOrganization credit balance cannot cover the scan
CONCURRENCY_LIMITAll concurrent slots in use; request may be queued
QUEUE_LIMITQueued-scan depth for the plan is full
RATE_LIMITEDHourly or daily request cap hit
BULK_LIMITToo many URLs for the caller’s bulk allowance
SUBSCRIPTION_INACTIVEPaid subscription past grace — update billing
NOT_FOUNDUnknown scan or bulk job id
PRIVATE_ADDRESS / BLOCKED_*Target refused for safety (SSRFs, ports)
08

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.

Request rate limits
CallerPer hourPer day
Anonymous (IP)510
Registered / API key60300

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 pricing and individual scan capacity
PlanPriceCredits / moConcurrentAPI
FreeFree1001
Developer$12/mo1,0003Yes
Growth$39/mo5,00010Yes
Scale$99/mo20,00025Yes
Enterprise$249/mo75,00050Yes

Bulk job size

Maximum URLs in a single bulk request. Enterprise is negotiated. Free requires an upgrade when credits enforcement is on.

URLs per bulk job
PlanURLs / job
Anonymous5 URLs
FreeUpgrade required
Developer100 URLs
Growth500 URLs
Scale2,500 URLs
EnterpriseCustom

Deeper scan modes, scheduled jobs, team seats, and overage pricing also differ by plan — see the full pricing page.

09

Next steps

Enterprise capacity or a custom bulk ceiling: hello@pluginview.com.