DOCUMENTATION

    How Onyx works, end to end.

    Everything from the moment you paste a spec URL to the final severity-scored result streaming to your dashboard. The full pipeline, the safeguards, and the answers to the questions people ask most.

    What is Onyx?

    Onyx is an AI-native API penetration-testing platform. You provide a link to any API's documentation, an OpenAPI / Swagger specification, and it autonomously verifies ownership, parses every endpoint, generates schema-aware attack payloads with Google Gemini 2.5 Flash, fires them through a rate-limited distributed queue, and streams severity-scored results back live.

    Unlike a generic fuzzer, Onyx reads your actual schema: request bodies, path parameters, query strings, and asks an LLM to reason about what would break each specific endpoint. The result is context-sensitive coverage across the OWASP Top 10 without writing a single test case by hand.

    8
    Attack categories
    400+
    Payloads / run
    5
    Concurrent workers
    0-100
    Security score

    Quick start

    Five steps take you from sign-up to a live, scored attack run. Each one is covered in more depth further down.

    1

    Create an account

    Sign up with an email and password. The Free plan needs no credit card and gives you 5 runs a month.

    2

    Paste a spec URL

    Drop your OpenAPI / Swagger URL into the dashboard. Onyx parses every endpoint the moment it loads.

    3

    Verify the domain

    Prove ownership once via a file or DNS record. The Execute Run button unlocks the instant it passes.

    4

    Execute the run

    Onyx generates payloads, queues them, and fires. Watch results stream in live, no refresh needed.

    5

    Review & export

    Triage findings by CVSS severity, drill into any endpoint, and export a PDF report on Pro and Team.

    No setup, no agents

    Onyx runs entirely from the spec URL. There's nothing to install on your servers and no SDK to wire in. If your API publishes an OpenAPI document, you're ready.

    What you can paste

    Every modern API ships a machine-readable spec describing its endpoints, parameters, and response formats, written in OpenAPI (formerly Swagger). Most APIs expose it at a path like /openapi.json, /swagger.json, or /v2/api-docs.

    Valid targets

    • petstore.swagger.io/v2/swagger.json
    • api.example.com/openapi.json
    • httpbin.org/spec.json

    Blocked

    • google.com (HTML, not a spec)
    • 192.168.1.5/api (private IP, SSRF)
    • any domain you don't own
    SSRF protection is strictly enforced

    Onyx performs DNS resolution on every URL. Any hostname resolving to 127.x, 10.x, 172.16-31.x, 192.168.x, 169.254.x, .local, or .internal is instantly blocked.

    Can't find your spec URL?

    If your team uses Swagger UI, the spec is the JSON the UI loads. Open the network tab and look for the .json request, or try appending one of these common paths to your API's base URL:

    /openapi.json
    /swagger.json
    /v2/api-docs
    /v3/api-docs
    /swagger/v1/swagger.json

    Domain ownership verification

    Before Onyx fires a single payload, you must prove you own the target domain. Without it, anyone could point Onyx at someone else's API. Verification closes that liability and is required once per domain, per account.

    Host a file containing only your verification token at this exact path. No quotes, no extra whitespace, nothing else:

    https://your-domain.com/.well-known/onyx-verify.txt
    
    onyx-verify-a3f9c2b1...
    Verification is permanent

    Once verified, a domain stays verified for your account. You can delete the file or DNS record afterward. DNS can take a few minutes to propagate; if a check fails right after saving the record, wait and retry.

    What actually happens

    Onyx extracts the hostname from your URL, generates a unique onyx-verify-<token>, and stores it against your account. When you click Check Verification, it probes the file over HTTPS first (retrying over HTTP if the connection fails), then falls back to a DNS TXT lookup. Whichever it finds first wins, and the run button unlocks.

    Until a domain is verified, every attempt to scan it is rejected before a single request leaves the server:

    POST /api/test-runs  ->  403 Forbidden
    
    {
      "error": "DOMAIN_NOT_VERIFIED",
      "domain": "target-api.com",
      "message": "You must verify ownership of
                  \"target-api.com\" before scanning it."
    }

    The attack flow

    End to end, from clicking Execute Run to receiving live results:

    1. 01

      Parse. The spec is fetched with WAF-bypass headers, then every endpoint, parameter, and request body is extracted.

    2. 02

      Generate. Gemini crafts up to 20 schema-aware payloads per endpoint (with a 35-payload static fallback).

    3. 03

      Queue. Payloads are added to a BullMQ Redis queue: 5 concurrent workers, 10 jobs/second, 10s timeout each.

    4. 04

      Fire. Each worker re-checks SSRF, fires the payload, and records status code, latency, and a response snippet.

    5. 05

      Score. Every result is classified with CVSS-inspired severity and folded into an overall 0-100 API security score.

    6. 06

      Stream. Results broadcast live to your dashboard over WebSockets as each attack completes.

    Run status phases

    As a run progresses, its status moves through four phases, and the dashboard reflects each one live:

    PARSING
    GENERATING
    ATTACKING
    COMPLETED

    Attack types generated

    Gemini produces strictly-typed JSON payloads across eight categories, each tuned to the endpoint under test:

    SQL_INJECTION

    Classic, blind, UNION, time-based, stacked, auth bypass

    XSS

    Reflected, stored, DOM, polyglot, event-handler vectors

    MISSING_AUTH

    Forged JWT (alg:none), missing headers, privilege escalation

    PATH_TRAVERSAL

    ../, URL-encoded, double-dot, Windows paths

    BOUNDARY

    Null bytes, integer overflow, empty strings, NaN

    OVERSIZED_PAYLOAD

    Array bombs (10k elements), deeply nested JSON

    TYPE_CONFUSION

    Strings where ints expected, arrays where strings expected

    RATE_LIMIT

    Burst markers to probe rate-limiting behaviour

    Live results

    HTTP polling is too slow for watching attacks land. Onyx opens an authenticated WebSocket and streams every result the instant a worker records it, and the dashboard's metrics, charts, and endpoint rows update without a refresh.

    Each event carries the method, endpoint, payload, status code, latency, and computed severity. A typical ATTACK_RESULT frame looks like this:

    {
      "type": "ATTACK_RESULT",
      "data": {
        "method": "POST",
        "endpoint": "/users/login",
        "statusCode": 500,
        "latency": 412,
        "attackType": "SQL_INJECTION",
        "severity": "CRITICAL"
      }
    }

    Per-run isolation

    Each run has its own subscriber set, so you only ever receive your own results.

    Heartbeat

    Ping/pong every 30s drops dead connections so the stream stays clean.

    Ownership-checked

    The server verifies you own a run in the database before allowing a subscription.

    CVSS severity scoring

    Each result is classified by status code and response content. The overall score starts at 100 and deducts per finding, giving you a single 0-100 number to track.

    CRITICAL5xx on an injection/auth attack, or secrets/DB errors leaked in the response-25
    HIGHAny other 5xx, or a 401/403 on an auth-bypass attempt-15
    MEDIUM4xx where the response leaks an error, stack, or trace-8
    LOWAny other 4xx response-3
    INFO2xx / 3xx / no response, no deduction0

    The final number maps to a label: CLEAN (100), LOW (76-99), MEDIUM (51-75), HIGH (26-50), and CRITICAL (0-25).

    Security & resilience

    Every run is fenced by layered guards, checked before and during the attack, so Onyx only ever hits the API you own.

    SSRF guard

    DNS resolution on every URL before any outbound request. Loopback, private, link-local, and cloud-metadata ranges are blocked at both spec-fetch and attack time.

    Domain ownership gate

    Every run checks for a verified (user, domain) record. No verified record returns a 403 before anything fires.

    Rate limiting

    Auth endpoints: 5 req/min per IP. Attack endpoints: 5 req/hour per IP. Plan quotas enforced per calendar month.

    JWT security

    7-day token expiry; the server hard-crashes on boot if JWT_SECRET is missing, preventing weak-key deployments.

    WAF bypass (fetch only)

    Spec fetch spoofs a real Chrome user-agent so Cloudflare/AWS WAFs don't false-negative during parsing.

    Graceful AI fallback

    If Gemini fails, 35 static payloads keep every scan completing, so the pipeline never stalls.

    Architecture

    Onyx is a decoupled pipeline: a React client, a guarded Express API, an AI payload stage, a Redis-backed queue, and a worker pool, with Postgres for persistence and WebSockets for telemetry. Each stage hands off to the next, so a slow target never blocks the UI.

    1. 01

      Client. React + Vite on Vercel. Submits the spec URL and subscribes to the run over a WebSocket.

    2. 02

      API + guards. Express on Render. Auth, rate-limit, quota, domain gate, and SSRF checks run before anything fires.

    3. 03

      Gemini. Generates the payload set per endpoint, with a static fallback if the model is unavailable.

    4. 04

      BullMQ + Redis. A job queue fans payloads out to 5 concurrent workers at 10/sec, surviving restarts.

    5. 05

      Workers. Fire each payload, score the response by CVSS severity, and persist it.

    6. 06

      Postgres + WS. Results are written to Neon Postgres via Prisma and broadcast live to the browser.

    Built on React 18, Express 4, Prisma 7 + Neon Postgres, BullMQ 5 + Redis, Google Gemini 2.5 Flash, and Razorpay for billing.

    Plans & quotas

    Quotas are checked per calendar month before a run is created. Exceeding a limit returns a 429 QUOTA_EXCEEDED with an upgrade link.

    PlanPriceRunsEndpointsPDF
    Free$05 / mo10 / run-
    Pro$9 / mo100 / mo50 / run
    Team$18 / mo500 / moUnlimited

    Billing runs through Razorpay with webhook-verified plan upgrades, with no manual provisioning. Prices are charged in INR (₹900 / ₹1800 per month).

    Frequently asked

    Yes. Onyx requires domain ownership verification (via a file probe or DNS TXT record) before it will fire a single payload at any target. This is both a legal protection and a trust layer.

    Ready to break your API?

    Start free. No credit card required.

    Start free scan

    Glossary

    Plain-English definitions for the terms used throughout these docs.

    OpenAPI / Swagger
    A machine-readable description of an API's endpoints, parameters, and responses. Onyx's only required input.
    SSRF
    Server-Side Request Forgery, which tricks a server into calling internal resources. Onyx blocks it via DNS resolution on every URL.
    CVSS
    Common Vulnerability Scoring System. The industry standard Onyx's severity labels are inspired by.
    BullMQ
    A Redis-backed job queue. Onyx uses it to fire attacks concurrently without overwhelming the target or Node.js.
    WebSocket
    A persistent two-way connection. Onyx streams every attack result over it so the dashboard updates in real time.
    Domain verification
    Proof that you own a target, via a file probe or DNS TXT record, required once before scanning.