Open Source · MIT Licensed · Battle-tested

API testing without the pain

Spectest runs declarative HTTP tests straight from the CLI. Describe the request and the response you expect — no clients, no boilerplate, no ceremony. Ship confident APIs faster.

export default [
  {
    name: "Create User",
    endpoint: "/api/users",
    request: {
      method: "POST",
      body: { name: "John", email: "john@example.com" },
    },
    response: {
      status: 201,
      json: { name: "John", email: "john@example.com" },
    },
  },
];

Trusted by fast-moving engineering teams

NorthwindLedgerlyFathom LabsVoltwayCascade AIBeaconOrbitalRunway RoboticsMeridianSlateHarborPinecrestNimbus DataKestrelLumenNorthwindLedgerlyFathom LabsVoltwayCascade AIBeaconOrbitalRunway RoboticsMeridianSlateHarborPinecrestNimbus DataKestrelLumen
10k+ assertions/sec on a laptop
3 formats — JS, JSON & YAML
0 lines of boilerplate
100% deterministic record & replay
Why Spectest

Everything you need to test APIs, none of the boilerplate

A single, focused tool for HTTP API testing — declarative by design, fast by default, and built to live in your CI pipeline.

See it in action

Radically less code than traditional API tests

The same two test cases — a create and a duplicate-rejection — written the old way versus the Spectest way.

Traditional Testing

user.test.js
describe('User API', () => {
  it('creates a user', async () => {
    const res = await fetch('/api/users', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ name: 'John', email: 'john@example.com' })
    });

    expect(res.status).toBe(201);
    expect(res.headers.get('content-type')).toContain('application/json');

    const user = await res.json();
    expect(user).toHaveProperty('id');
    expect(user.name).toBe('John');
    expect(user.email).toBe('john@example.com');
  });

  it('rejects a duplicate email', async () => {
    const res = await fetch('/api/users', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ name: 'Jane', email: 'john@example.com' })
    });

    expect(res.status).toBe(409);
    const body = await res.json();
    expect(body.error).toBe('email already exists');
  });
});

Spectest

export default [
  {
    name: "Create User",
    endpoint: "/api/users",
    request: {
      method: "POST",
      body: { name: "John", email: "john@example.com" },
    },
    response: {
      status: 201,
      headers: { "content-type": /application\/json/ },
      json: { name: "John", email: "john@example.com" },
    },
  },
  {
    name: "Reject Duplicate Email",
    endpoint: "/api/users",
    request: {
      method: "POST",
      body: { name: "Jane", email: "john@example.com" },
    },
    response: {
      status: 409,
      json: { error: "email already exists" },
    },
  },
];
[
  {
    "name": "Create User",
    "endpoint": "/api/users",
    "request": {
      "method": "POST",
      "body": { "name": "John", "email": "john@example.com" }
    },
    "response": {
      "status": 201,
      "headers": { "content-type": "application/json" },
      "json": { "name": "John", "email": "john@example.com" }
    }
  },
  {
    "name": "Reject Duplicate Email",
    "endpoint": "/api/users",
    "request": {
      "method": "POST",
      "body": { "name": "Jane", "email": "john@example.com" }
    },
    "response": {
      "status": 409,
      "json": { "error": "email already exists" }
    }
  }
]
- name: Create User
  endpoint: /api/users
  request:
    method: POST
    body:
      name: John
      email: john@example.com
  response:
    status: 201
    headers:
      content-type: application/json
    json:
      name: John
      email: john@example.com

- name: Reject Duplicate Email
  endpoint: /api/users
  request:
    method: POST
    body:
      name: Jane
      email: john@example.com
  response:
    status: 409
    json:
      error: email already exists
That’s it. No setup, no boilerplate, no ceremony. Describe what you expect and Spectest handles execution, validation, and reporting.
Loved by developers

Teams ship with confidence on Spectest

From fintech platforms to developer-tool startups, engineers use Spectest to keep their APIs honest.

"We deleted 2,000 lines of supertest glue and replaced it with declarative Spectest suites. CI got faster and our tests finally read like documentation."
Staff Engineer Fintech platform team
"OpenAPI-native execution means our spec is the test. If the API drifts from the contract, Spectest catches it before it ships."
API Lead Developer tools startup
"Record-and-replay made our flaky integration tests deterministic overnight. It's the first testing tool the whole team actually enjoys using."
Engineering Manager B2B SaaS
Feature deep dive

Built to be feature-rich and robust

The capabilities teams reach for once tests move beyond a single happy-path request.

OpenAPI native

Your spec is your test suite

Point Spectest at an OpenAPI 3.0 or 3.1 document and run its operations directly — no hand-written suite required. Catch contract drift the moment your implementation diverges from the spec, right in CI.

OpenAPI testing guide
# Run every operation defined in your spec
npx spectest --openapi ./openapi.yaml

  ✓ GET /users          200  (12ms)
  ✓ POST /users         201  (18ms)
  ✓ GET /users/{id}     200  (9ms)
  ✓ DELETE /users/{id}  204  (7ms)

  4 passed · 0 failed · 46ms
Deterministic by design

Record once, replay forever

Capture the outbound HTTP calls your server makes to third parties, then replay them deterministically on every run. Flaky integration tests become reproducible, offline-friendly, and fast.

Record & replay guide
export default {
  name: "Checkout charges Stripe",
  endpoint: "/api/checkout",
  request: { method: "POST", body: { plan: "pro" } },
  // Outbound call to Stripe is recorded on first
  // run, then replayed on every run after.
  record: "./fixtures/stripe.har",
  response: { status: 200, json: { paid: true } },
};
Powerful assertions

Match exactly what matters

Assert on status, headers, and bodies with deep JSON matching, regex, partial objects, snapshots, and Zod schemas. Ignore volatile fields like timestamps and IDs without brittle string comparisons.

Schema assertions
import { z } from "zod";

export default {
  name: "List users",
  endpoint: "/api/users",
  response: {
    status: 200,
    schema: z.array(
      z.object({
        id: z.string().uuid(),
        email: z.string().email(),
      })
    ),
  },
};
Comparison

How Spectest stacks up

An honest look at how Spectest compares to the tools teams reach for today. Every option has its place — Spectest is built for fast, declarative, CI-first API testing.

CapabilitySpectestPostman/Newmansupertest + JestBruno
Declarative, zero-boilerplate tests~~
Runs from the CLI & CI natively~
JS · JSON · YAML suites~
OpenAPI 3.0/3.1 native execution~
Record & replay outbound HTTP
Snapshot testing~
Zod & schema assertions~
No GUI or account required
Fully open source (MIT)

Built in  ·  ~ Partial / via plugin  ·  Not supported

Quick start

From zero to your first passing test in minutes

Install the CLI, point it at your API, and describe what you expect.

Install Spectest

npm install -g spectest

Create a Config File

// spectest.config.js
export default {
  baseUrl: "https://api.example.com",
  testDir: "./test",
  filePattern: "\.spectest\.",
};

Create Your First Test

// health.spectest.js
export default [
  { name: "Health Check", endpoint: "/health", response: { status: 200 } },
];

Run Your Tests

npx spectest
Integrations

Fits the stack you already use

Spectest plays nicely with your test runner, your schemas, and your API contracts.

Ready to transform your API testing?

Install Spectest today and write your first declarative test in under five minutes. It's free, open source, and MIT licensed.

Open Source & MIT Licensed

Spectest is free, open-source software released under the MIT license. Use it anywhere, modify it as needed, and contribute back to help make API testing better for everyone.