BookNest testing sandbox

Testing API

Expandable REST reference for functional, negative, stateful, concurrency and resilience PoCs.

Using the API

Base URL/api/v1Current environment
Execution isolationSend X-Test-Run-Id; the default is shared-demo.
Anonymous cartsKeep the same X-Client-Id until login to test cart merging.
AuthenticationUse the bearer token returned by login. Test controls also require X-Test-Admin-Key.
REST reference

18 operations

Select an operation to view parameters, typed body fields, request and response examples, and status codes.

GET/healthService healthDetails

Returns a lightweight service and version check. It does not read or mutate test-run state.

Parameters and headers

No endpoint-specific values are required.

Request body

This operation does not accept a request body.

Example request

curl "/api/v1/health"

Example response · 200

{
  "status": "ok",
  "service": "booknest-api",
  "version": "1.0",
  "time": "2026-09-10T18:30:00.000Z"
}

Status codes

200Service is running.
500Unexpected service failure.
GET/booksSearch and filter booksDetails

Returns a paginated catalogue. Combine search, category, price, availability and sorting parameters to create dynamic-data assertions.

Parameters and headers

NameLocationTypeRequiredDescriptionExample
X-Test-Run-IdheaderstringOptionalIsolates state for one automation execution; defaults to shared-demo.poc-run-001
X-Test-Defectsheaderstring (comma-separated enum)OptionalActivates deterministic intentional defects. Values: smoke, ui, functional, validation, api, state. The equivalent defects query parameter is also supported.api,state
queryquerystringOptionalCase-insensitive title, author, ISBN or category search.algorithm
categoryquerystringOptionalExact category name or All categories.Mystery
availableOnlyquerybooleanOptionalWhen true, hides books with zero stock.true
maxPricequerynumberOptionalMaximum price in USD.25
sortquerystring enumOptionalfeatured, price-low, price-high, rating or newest.price-low
pagequeryintegerOptionalOne-based page number; defaults to 1.1
pageSizequeryintegerOptionalItems per page from 1 to 100; defaults to 20.20

Request body

This operation does not accept a request body.

Example request

curl "/api/v1/books?query=algorithm&availableOnly=true&page=1&pageSize=20" \
+  -H "X-Test-Run-Id: poc-run-001"

Example response · 200

{
  "items": [
    {
      "id": 10,
      "title": "The Quiet Algorithm",
      "author": "Daniel Cho",
      "category": "Mystery",
      "price": 15.99,
      "rating": 4.7,
      "stock": 12,
      "format": "Hardcover",
      "year": 2018,
      "isbn": "978-1-4209-19-9",
      "inventoryVersion": 1
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 20,
  "runId": "poc-run-001",
  "scenario": "normal"
}

Status codes

200Catalogue page returned, including valid empty results.
429The rate-limited scenario has exceeded its request allowance.
500An intermittent failure occurred or an unexpected server error was handled.
503The service-unavailable scenario is active.
GET/books/{id}Book detailsDetails

Returns one synthetic title with current run-specific stock, price and inventory version.

Parameters and headers

NameLocationTypeRequiredDescriptionExample
X-Test-Run-IdheaderstringOptionalIsolates state for one automation execution; defaults to shared-demo.poc-run-001
idpathintegerRequiredNumeric book identifier.10

Request body

This operation does not accept a request body.

Example request

curl "/api/v1/books/10" -H "X-Test-Run-Id: poc-run-001"

Example response · 200

{
  "id": 10,
  "title": "The Quiet Algorithm",
  "author": "Daniel Cho",
  "category": "Mystery",
  "price": 15.99,
  "stock": 12,
  "format": "Hardcover",
  "inventoryVersion": 1
}

Status codes

200Book returned.
404Book ID does not exist.
429The rate-limited scenario has exceeded its request allowance.
500An intermittent failure occurred or an unexpected server error was handled.
503The service-unavailable scenario is active.
POST/auth/registerRegister a customerDetails

Creates a synthetic customer inside the selected test run. Email uniqueness is scoped to that run.

Parameters and headers

NameLocationTypeRequiredDescriptionExample
X-Test-Run-IdheaderstringOptionalIsolates state for one automation execution; defaults to shared-demo.poc-run-001

JSON request body

NameLocationTypeRequiredDescriptionExample
firstNamebodystringRequiredCustomer first name; blank values are rejected.Taylor
lastNamebodystringRequiredCustomer last name; blank values are rejected.Reed
emailbodystring (email)RequiredValid email address, unique within the test run.taylor.reed@example.com
passwordbodystringRequiredAt least 8 characters with one uppercase letter and one number.Testing123!
confirmbodystringOptionalWhen supplied, must exactly match password.Testing123!

Example request

curl -X POST "/api/v1/auth/register" \
+  -H "Content-Type: application/json" -H "X-Test-Run-Id: poc-run-001" \
+  -d '{"firstName":"Taylor","lastName":"Reed","email":"taylor.reed@example.com","password":"Testing123!","confirm":"Testing123!"}'

Example response · 201

{
  "id": "13d6e43b-409a-4fb3-846c-16b80a25c472",
  "email": "taylor.reed@example.com",
  "firstName": "Taylor",
  "lastName": "Reed"
}

Status codes

201Customer created.
400Body is not valid JSON.
409Email already exists in this test run.
422Name, email, password or confirmation validation failed.
429The rate-limited scenario has exceeded its request allowance.
500An intermittent failure occurred or an unexpected server error was handled.
503The service-unavailable scenario is active.
POST/auth/loginCreate a bearer sessionDetails

Authenticates a synthetic customer for one hour and merges items from the matching anonymous client cart.

Parameters and headers

NameLocationTypeRequiredDescriptionExample
X-Test-Run-IdheaderstringOptionalIsolates state for one automation execution; defaults to shared-demo.poc-run-001
X-Client-IdheaderstringOptionalIdentifies an anonymous cart and allows it to merge after login.browser-001

JSON request body

NameLocationTypeRequiredDescriptionExample
emailbodystring (email)RequiredRegistered email or the seeded demo email.customer@example.com
passwordbodystringRequiredAccount password.Password123!

Example request

curl -X POST "/api/v1/auth/login" \
+  -H "Content-Type: application/json" -H "X-Test-Run-Id: poc-run-001" -H "X-Client-Id: browser-001" \
+  -d '{"email":"customer@example.com","password":"Password123!"}'

Example response · 200

{
  "token": "550e8400-e29b-41d4-a716-446655440000",
  "expiresAt": 1789071000000,
  "user": {
    "id": "seed-poc-run-001",
    "email": "customer@example.com",
    "firstName": "Alex",
    "lastName": "Morgan"
  },
  "cartMerged": true
}

Status codes

200Authenticated; bearer token returned.
400Body is not valid JSON.
401Email or password is incorrect.
429The rate-limited scenario has exceeded its request allowance.
500An intermittent failure occurred or an unexpected server error was handled.
503The service-unavailable scenario is active.
POST/auth/logoutInvalidate a sessionDetails

Deletes the supplied bearer session. Repeating the request is safe and still returns success.

SecurityBearer token recommended; a missing token is treated as an already-signed-out session.

Parameters and headers

NameLocationTypeRequiredDescriptionExample
AuthorizationheaderstringOptionalBearer token returned by POST /auth/login.Bearer <token>

Request body

This operation does not accept a request body.

Example request

curl -X POST "/api/v1/auth/logout" -H "Authorization: Bearer <token>"

Example response · 200

{
  "signedOut": true
}

Status codes

200Session invalidated or already absent.
500Unexpected persistence failure.
GET/cartRead the current cartDetails

Returns the anonymous or authenticated cart selected by the request headers, with calculated USD totals.

Parameters and headers

NameLocationTypeRequiredDescriptionExample
X-Test-Run-IdheaderstringOptionalIsolates state for one automation execution; defaults to shared-demo.poc-run-001
X-Client-IdheaderstringOptionalIdentifies an anonymous cart and allows it to merge after login.browser-001
AuthorizationheaderstringOptionalBearer token returned by POST /auth/login.Bearer <token>

Request body

This operation does not accept a request body.

Example request

curl "/api/v1/cart" -H "X-Test-Run-Id: poc-run-001" -H "X-Client-Id: browser-001"

Example response · 200

{
  "ownerKey": "guest:browser-001",
  "items": [],
  "itemCount": 0,
  "promoCode": null,
  "promoState": "none",
  "subtotal": 0,
  "discount": 0,
  "shipping": 0,
  "total": 0,
  "updatedAt": 1789069000000
}

Status codes

200Cart returned.
401Supplied bearer session has expired.
429The rate-limited scenario has exceeded its request allowance.
500An intermittent failure occurred or an unexpected server error was handled.
503The service-unavailable scenario is active.
POST/cartAdd a book to the cartDetails

Adds the requested quantity to any existing quantity and records the current price snapshot.

Parameters and headers

NameLocationTypeRequiredDescriptionExample
X-Test-Run-IdheaderstringOptionalIsolates state for one automation execution; defaults to shared-demo.poc-run-001
X-Client-IdheaderstringOptionalIdentifies an anonymous cart and allows it to merge after login.browser-001
AuthorizationheaderstringOptionalBearer token returned by POST /auth/login.Bearer <token>

JSON request body

NameLocationTypeRequiredDescriptionExample
bookIdbodyintegerRequiredBook to add.10
quantitybodyintegerOptionalPositive amount to add; defaults to 1.1

Example request

curl -X POST "/api/v1/cart" -H "Content-Type: application/json" \
+  -H "X-Test-Run-Id: poc-run-001" -H "X-Client-Id: browser-001" -d '{"bookId":10,"quantity":1}'

Example response · 201

{
  "ownerKey": "guest:browser-001",
  "items": [
    {
      "book": {
        "id": 10,
        "title": "The Quiet Algorithm",
        "price": 15.99
      },
      "quantity": 1,
      "priceSnapshot": 15.99
    }
  ],
  "itemCount": 1,
  "subtotal": 15.99,
  "discount": 0,
  "shipping": 4.99,
  "total": 20.98
}

Status codes

201Book added and cart returned.
400Body is not valid JSON.
404Book ID does not exist.
409Book is out of stock or requested total exceeds stock.
429The rate-limited scenario has exceeded its request allowance.
500An intermittent failure occurred or an unexpected server error was handled.
503The service-unavailable scenario is active.
PATCH/cartSet a cart quantityDetails

Replaces the quantity for one book. Quantity zero removes the line and any applied promotion is cleared.

Parameters and headers

NameLocationTypeRequiredDescriptionExample
X-Test-Run-IdheaderstringOptionalIsolates state for one automation execution; defaults to shared-demo.poc-run-001
X-Client-IdheaderstringOptionalIdentifies an anonymous cart and allows it to merge after login.browser-001
AuthorizationheaderstringOptionalBearer token returned by POST /auth/login.Bearer <token>

JSON request body

NameLocationTypeRequiredDescriptionExample
bookIdbodyintegerRequiredExisting book identifier.10
quantitybodyintegerRequiredNew non-negative quantity; zero removes the item.2

Example request

curl -X PATCH "/api/v1/cart" -H "Content-Type: application/json" \
+  -H "X-Test-Run-Id: poc-run-001" -H "X-Client-Id: browser-001" -d '{"bookId":10,"quantity":2}'

Example response · 200

{
  "ownerKey": "guest:browser-001",
  "itemCount": 2,
  "promoState": "none",
  "subtotal": 31.98,
  "discount": 0,
  "shipping": 4.99,
  "total": 36.97
}

Status codes

200Quantity updated and cart returned.
400Body is not valid JSON.
404Book ID does not exist.
409Quantity exceeds current stock.
422Quantity is negative or is not an integer.
429The rate-limited scenario has exceeded its request allowance.
500An intermittent failure occurred or an unexpected server error was handled.
503The service-unavailable scenario is active.
DELETE/cartRemove cart itemsDetails

Removes one line when bookId is supplied, otherwise clears all lines. Promotions are also cleared.

Parameters and headers

NameLocationTypeRequiredDescriptionExample
X-Test-Run-IdheaderstringOptionalIsolates state for one automation execution; defaults to shared-demo.poc-run-001
X-Client-IdheaderstringOptionalIdentifies an anonymous cart and allows it to merge after login.browser-001
AuthorizationheaderstringOptionalBearer token returned by POST /auth/login.Bearer <token>
bookIdqueryintegerOptionalBook to remove; omit to clear the complete cart.10

Request body

This operation does not accept a request body.

Example request

curl -X DELETE "/api/v1/cart?bookId=10" -H "X-Test-Run-Id: poc-run-001" -H "X-Client-Id: browser-001"

Example response · 200

{
  "ownerKey": "guest:browser-001",
  "items": [],
  "itemCount": 0,
  "promoCode": null,
  "promoState": "none",
  "subtotal": 0,
  "discount": 0,
  "shipping": 0,
  "total": 0
}

Status codes

200Requested cart lines removed.
429The rate-limited scenario has exceeded its request allowance.
500An intermittent failure occurred or an unexpected server error was handled.
503The service-unavailable scenario is active.
POST/promotions/validateApply a promotionDetails

Validates and attaches a promotion to the current cart. BOOK10 is valid; EXPIRED20 and unknown values exercise negative paths.

Parameters and headers

NameLocationTypeRequiredDescriptionExample
X-Test-Run-IdheaderstringOptionalIsolates state for one automation execution; defaults to shared-demo.poc-run-001
X-Client-IdheaderstringOptionalIdentifies an anonymous cart and allows it to merge after login.browser-001
AuthorizationheaderstringOptionalBearer token returned by POST /auth/login.Bearer <token>

JSON request body

NameLocationTypeRequiredDescriptionExample
codebodystringRequiredCase-insensitive promotional code.BOOK10

Example request

curl -X POST "/api/v1/promotions/validate" -H "Content-Type: application/json" \
+  -H "X-Test-Run-Id: poc-run-001" -H "X-Client-Id: browser-001" -d '{"code":"BOOK10"}'

Example response · 200

{
  "code": "BOOK10",
  "valid": true,
  "discountPercent": 10,
  "message": "10% discount applied."
}

Status codes

200BOOK10 applied.
400Body is not valid JSON.
422Code is expired or unknown.
429The rate-limited scenario has exceeded its request allowance.
500An intermittent failure occurred or an unexpected server error was handled.
503The service-unavailable scenario is active.
GET/ordersList order historyDetails

Returns orders for the authenticated customer in the selected test run, newest first.

SecurityBearer token required.

Parameters and headers

NameLocationTypeRequiredDescriptionExample
X-Test-Run-IdheaderstringOptionalIsolates state for one automation execution; defaults to shared-demo.poc-run-001
AuthorizationheaderstringRequiredBearer token returned by POST /auth/login.Bearer <token>

Request body

This operation does not accept a request body.

Example request

curl "/api/v1/orders" -H "X-Test-Run-Id: poc-run-001" -H "Authorization: Bearer <token>"

Example response · 200

{
  "items": [
    {
      "id": "BN-2026-483921",
      "status": "Confirmed",
      "subtotal": 31.98,
      "discount": 3.2,
      "shipping": 4.99,
      "total": 33.77,
      "itemCount": 2,
      "date": "2026-09-10T18:30:00.000Z"
    }
  ]
}

Status codes

200Order history returned; items may be empty.
401Authentication is missing or the session expired.
429The rate-limited scenario has exceeded its request allowance.
500An intermittent failure occurred or an unexpected server error was handled.
503The service-unavailable scenario is active.
POST/ordersPlace a simulated orderDetails

Checks delivery fields, current inventory and price snapshots, then creates one idempotent order and clears the cart.

SecurityBearer token required. Use a stable Idempotency-Key when retrying the same checkout.

Parameters and headers

NameLocationTypeRequiredDescriptionExample
X-Test-Run-IdheaderstringOptionalIsolates state for one automation execution; defaults to shared-demo.poc-run-001
AuthorizationheaderstringRequiredBearer token returned by POST /auth/login.Bearer <token>
Idempotency-KeyheaderstringOptionalReturns the existing order when the same value is retried in one run.checkout-001

JSON request body

NameLocationTypeRequiredDescriptionExample
addressbodystringRequiredSynthetic street address.10 Test Avenue
citybodystringRequiredDelivery city.Boston
postalbodystringRequiredPostal code.02108

Example request

curl -X POST "/api/v1/orders" -H "Content-Type: application/json" \
+  -H "Authorization: Bearer <token>" -H "X-Test-Run-Id: poc-run-001" -H "Idempotency-Key: checkout-001" \
+  -d '{"address":"10 Test Avenue","city":"Boston","postal":"02108"}'

Example response · 201

{
  "id": "BN-2026-483921",
  "status": "Confirmed",
  "subtotal": 31.98,
  "discount": 3.2,
  "shipping": 4.99,
  "total": 33.77,
  "itemCount": 2,
  "idempotentReplay": false
}

Status codes

200Existing order returned for an idempotent replay.
201Order created.
400Body is not valid JSON.
401Authentication is missing or expired.
409Inventory or price changed after cart creation.
422Delivery fields are missing, cart is empty, or simulated payment was declined.
429The rate-limited scenario has exceeded its request allowance.
500An intermittent failure occurred or an unexpected server error was handled.
503The service-unavailable scenario is active.
POST/orders/{id}/cancelCancel an orderDetails

Cancels an authenticated customer's order and restores its inventory. Repeating a successful cancellation is idempotent.

SecurityBearer token required.

Parameters and headers

NameLocationTypeRequiredDescriptionExample
X-Test-Run-IdheaderstringOptionalIsolates state for one automation execution; defaults to shared-demo.poc-run-001
AuthorizationheaderstringRequiredBearer token returned by POST /auth/login.Bearer <token>
idpathstringRequiredBookNest order number.BN-2026-483921

Request body

This operation does not accept a request body.

Example request

curl -X POST "/api/v1/orders/BN-2026-483921/cancel" \
+  -H "X-Test-Run-Id: poc-run-001" -H "Authorization: Bearer <token>"

Example response · 200

{
  "id": "BN-2026-483921",
  "status": "Cancelled",
  "stockRestored": true
}

Status codes

200Order cancelled or already cancelled.
401Authentication is missing or expired.
404Order is absent, belongs to another customer, or belongs to another run.
429The rate-limited scenario has exceeded its request allowance.
500An intermittent failure occurred or an unexpected server error was handled.
503The service-unavailable scenario is active.
GET/test/defectsDiscover intentional defect packsDetails

Returns every supported defect pack, its stable defect IDs, expected behavior and intentionally defective behavior. It also reports packs activated on this request. This discovery operation is public, stateless and does not require the admin key.

Parameters and headers

NameLocationTypeRequiredDescriptionExample
X-Test-Defectsheaderstring (comma-separated enum)OptionalActivates deterministic intentional defects. Values: smoke, ui, functional, validation, api, state. The equivalent defects query parameter is also supported.api,state
defectsquerystring (comma-separated enum)OptionalAlternative to X-Test-Defects. Combine packs with commas.smoke,ui

Request body

This operation does not accept a request body.

Example request

curl "/api/v1/test/defects?defects=smoke"

Example response · 200

{
  "activePacks": [
    "smoke"
  ],
  "activeDefectIds": [
    "DEF-NAV-001",
    "DEF-SEARCH-001",
    "DEF-CART-001",
    "DEF-AUTH-001",
    "DEF-CHECKOUT-001"
  ],
  "packs": [
    {
      "name": "smoke",
      "label": "Smoke defects",
      "description": "Obvious failures across navigation, search, cart, authentication, and checkout.",
      "defects": [
        {
          "id": "DEF-NAV-001",
          "title": "Home logo is inert",
          "expected": "Selecting the BookNest brand resets the storefront.",
          "defective": "The brand control does nothing."
        }
      ]
    }
  ],
  "usage": {
    "storefront": "/?defects=smoke",
    "apiQuery": "/api/v1/books?defects=api",
    "apiHeader": "X-Test-Defects: api",
    "combine": "/?defects=ui,functional",
    "disable": "Remove the defects query parameter or X-Test-Defects header."
  }
}

Status codes

200Defect catalogue and current activation returned.
GET/test/scenarioRead scenario stateDetails

Returns the selected run's active scenario and settings, plus every scenario's editable parameter metadata, defaults, types and limits.

SecurityX-Test-Admin-Key required. Keep it out of screenshots and recorded public test artifacts.

Parameters and headers

NameLocationTypeRequiredDescriptionExample
X-Test-Run-IdheaderstringOptionalIsolates state for one automation execution; defaults to shared-demo.poc-run-001
X-Test-Admin-KeyheaderstringRequiredProtected deployment secret for scenario and reset operations.<test-admin-key>

Request body

This operation does not accept a request body.

Example request

curl "/api/v1/test/scenario" -H "X-Test-Run-Id: poc-run-001" -H "X-Test-Admin-Key: <test-admin-key>"

Example response · 200

{
  "runId": "poc-run-001",
  "active": {
    "scenario": "slow-api",
    "requestCount": 0,
    "settings": {
      "delayMs": 3500
    },
    "settingsJson": "{\"delayMs\":3500}",
    "updatedAt": 1789069000000
  },
  "available": [
    {
      "value": "slow-api",
      "label": "Slow API",
      "description": "Adds a deterministic delay to business requests.",
      "settings": [
        {
          "key": "delayMs",
          "label": "Response delay",
          "type": "number",
          "defaultValue": 2000,
          "min": 0,
          "max": 15000,
          "unit": "ms",
          "description": "Delay applied before the API responds."
        }
      ]
    }
  ]
}

Status codes

200Scenario state and editable parameter definitions returned.
403Admin key is missing or invalid.
500Unexpected persistence failure.
POST/test/scenarioActivate a test scenarioDetails

Sets one deterministic failure or data mode and resets its request counter for the selected run.

SecurityX-Test-Admin-Key required.

Parameters and headers

NameLocationTypeRequiredDescriptionExample
X-Test-Run-IdheaderstringOptionalIsolates state for one automation execution; defaults to shared-demo.poc-run-001
X-Test-Admin-KeyheaderstringRequiredProtected deployment secret for scenario and reset operations.<test-admin-key>

JSON request body

NameLocationTypeRequiredDescriptionExample
scenariobodystring enumRequirednormal, slow-api, intermittent-error, service-unavailable, rate-limited, expired-session, inventory-conflict, price-change, payment-decline, partial-response, empty-catalogue, large-catalogue or malformed-response.slow-api
settingsbodyobjectOptionalScenario-specific key/value map. GET this endpoint for supported keys, types, defaults and limits. Unknown keys are discarded; missing or out-of-range values are normalized.{"delayMs":3500}

Example request

curl -X POST "/api/v1/test/scenario" -H "Content-Type: application/json" \
+  -H "X-Test-Run-Id: poc-run-001" -H "X-Test-Admin-Key: <test-admin-key>" -d '{"scenario":"slow-api","settings":{"delayMs":3500}}'

Example response · 200

{
  "runId": "poc-run-001",
  "scenario": "slow-api",
  "settings": {
    "delayMs": 3500
  },
  "requestCount": 0,
  "updatedAt": 1789069000000
}

Status codes

200Scenario activated and normalized settings returned.
400Body is not valid JSON.
403Admin key is missing or invalid.
422Scenario name is unsupported.
500Unexpected persistence failure.
POST/test/resetReset one isolated test runDetails

Deletes users, sessions, carts, inventory overrides, orders and scenario state only for the selected run.

SecurityX-Test-Admin-Key required. This is destructive within the supplied X-Test-Run-Id only.

Parameters and headers

NameLocationTypeRequiredDescriptionExample
X-Test-Run-IdheaderstringOptionalIsolates state for one automation execution; defaults to shared-demo.poc-run-001
X-Test-Admin-KeyheaderstringRequiredProtected deployment secret for scenario and reset operations.<test-admin-key>

Request body

This operation does not accept a request body.

Example request

curl -X POST "/api/v1/test/reset" -H "X-Test-Run-Id: poc-run-001" -H "X-Test-Admin-Key: <test-admin-key>"

Example response · 200

{
  "reset": true,
  "runId": "poc-run-001",
  "scenario": "normal",
  "message": "All synthetic state for this test run was removed."
}

Status codes

200Selected run reset.
403Admin key is missing or invalid.
500Unexpected persistence failure.

Standard error response

Errors use one predictable envelope so API assertions can validate both business failures and simulated resilience scenarios.

{
  "error": {
    "status": 422,
    "code": "VALIDATION_ERROR",
    "message": "The request could not be processed.",
    "details": null
  },
  "traceId": "4f7bcd8b-35a8-47e4-a380-c245c28b318f"
}