Testing API
Expandable REST reference for functional, negative, stateful, concurrency and resilience PoCs.
Using the API
/api/v1Current environmentX-Test-Run-Id; the default is shared-demo.X-Client-Id until login to test cart merging.X-Test-Admin-Key.18 operations
Select an operation to view parameters, typed body fields, request and response examples, and status codes.
GET/healthService health
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 books
Returns a paginated catalogue. Combine search, category, price, availability and sorting parameters to create dynamic-data assertions.
Parameters and headers
| Name | Location | Type | Required | Description | Example |
|---|---|---|---|---|---|
X-Test-Run-Id | header | string | Optional | Isolates state for one automation execution; defaults to shared-demo. | poc-run-001 |
X-Test-Defects | header | string (comma-separated enum) | Optional | Activates deterministic intentional defects. Values: smoke, ui, functional, validation, api, state. The equivalent defects query parameter is also supported. | api,state |
query | query | string | Optional | Case-insensitive title, author, ISBN or category search. | algorithm |
category | query | string | Optional | Exact category name or All categories. | Mystery |
availableOnly | query | boolean | Optional | When true, hides books with zero stock. | true |
maxPrice | query | number | Optional | Maximum price in USD. | 25 |
sort | query | string enum | Optional | featured, price-low, price-high, rating or newest. | price-low |
page | query | integer | Optional | One-based page number; defaults to 1. | 1 |
pageSize | query | integer | Optional | Items 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 details
Returns one synthetic title with current run-specific stock, price and inventory version.
Parameters and headers
| Name | Location | Type | Required | Description | Example |
|---|---|---|---|---|---|
X-Test-Run-Id | header | string | Optional | Isolates state for one automation execution; defaults to shared-demo. | poc-run-001 |
id | path | integer | Required | Numeric 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 customer
Creates a synthetic customer inside the selected test run. Email uniqueness is scoped to that run.
Parameters and headers
| Name | Location | Type | Required | Description | Example |
|---|---|---|---|---|---|
X-Test-Run-Id | header | string | Optional | Isolates state for one automation execution; defaults to shared-demo. | poc-run-001 |
JSON request body
| Name | Location | Type | Required | Description | Example |
|---|---|---|---|---|---|
firstName | body | string | Required | Customer first name; blank values are rejected. | Taylor |
lastName | body | string | Required | Customer last name; blank values are rejected. | Reed |
email | body | string (email) | Required | Valid email address, unique within the test run. | taylor.reed@example.com |
password | body | string | Required | At least 8 characters with one uppercase letter and one number. | Testing123! |
confirm | body | string | Optional | When 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 session
Authenticates a synthetic customer for one hour and merges items from the matching anonymous client cart.
Parameters and headers
| Name | Location | Type | Required | Description | Example |
|---|---|---|---|---|---|
X-Test-Run-Id | header | string | Optional | Isolates state for one automation execution; defaults to shared-demo. | poc-run-001 |
X-Client-Id | header | string | Optional | Identifies an anonymous cart and allows it to merge after login. | browser-001 |
JSON request body
| Name | Location | Type | Required | Description | Example |
|---|---|---|---|---|---|
email | body | string (email) | Required | Registered email or the seeded demo email. | customer@example.com |
password | body | string | Required | Account 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 session
Deletes the supplied bearer session. Repeating the request is safe and still returns success.
Parameters and headers
| Name | Location | Type | Required | Description | Example |
|---|---|---|---|---|---|
Authorization | header | string | Optional | Bearer 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 cart
Returns the anonymous or authenticated cart selected by the request headers, with calculated USD totals.
Parameters and headers
| Name | Location | Type | Required | Description | Example |
|---|---|---|---|---|---|
X-Test-Run-Id | header | string | Optional | Isolates state for one automation execution; defaults to shared-demo. | poc-run-001 |
X-Client-Id | header | string | Optional | Identifies an anonymous cart and allows it to merge after login. | browser-001 |
Authorization | header | string | Optional | Bearer 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 cart
Adds the requested quantity to any existing quantity and records the current price snapshot.
Parameters and headers
| Name | Location | Type | Required | Description | Example |
|---|---|---|---|---|---|
X-Test-Run-Id | header | string | Optional | Isolates state for one automation execution; defaults to shared-demo. | poc-run-001 |
X-Client-Id | header | string | Optional | Identifies an anonymous cart and allows it to merge after login. | browser-001 |
Authorization | header | string | Optional | Bearer token returned by POST /auth/login. | Bearer <token> |
JSON request body
| Name | Location | Type | Required | Description | Example |
|---|---|---|---|---|---|
bookId | body | integer | Required | Book to add. | 10 |
quantity | body | integer | Optional | Positive 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 quantity
Replaces the quantity for one book. Quantity zero removes the line and any applied promotion is cleared.
Parameters and headers
| Name | Location | Type | Required | Description | Example |
|---|---|---|---|---|---|
X-Test-Run-Id | header | string | Optional | Isolates state for one automation execution; defaults to shared-demo. | poc-run-001 |
X-Client-Id | header | string | Optional | Identifies an anonymous cart and allows it to merge after login. | browser-001 |
Authorization | header | string | Optional | Bearer token returned by POST /auth/login. | Bearer <token> |
JSON request body
| Name | Location | Type | Required | Description | Example |
|---|---|---|---|---|---|
bookId | body | integer | Required | Existing book identifier. | 10 |
quantity | body | integer | Required | New 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 items
Removes one line when bookId is supplied, otherwise clears all lines. Promotions are also cleared.
Parameters and headers
| Name | Location | Type | Required | Description | Example |
|---|---|---|---|---|---|
X-Test-Run-Id | header | string | Optional | Isolates state for one automation execution; defaults to shared-demo. | poc-run-001 |
X-Client-Id | header | string | Optional | Identifies an anonymous cart and allows it to merge after login. | browser-001 |
Authorization | header | string | Optional | Bearer token returned by POST /auth/login. | Bearer <token> |
bookId | query | integer | Optional | Book 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 promotion
Validates and attaches a promotion to the current cart. BOOK10 is valid; EXPIRED20 and unknown values exercise negative paths.
Parameters and headers
| Name | Location | Type | Required | Description | Example |
|---|---|---|---|---|---|
X-Test-Run-Id | header | string | Optional | Isolates state for one automation execution; defaults to shared-demo. | poc-run-001 |
X-Client-Id | header | string | Optional | Identifies an anonymous cart and allows it to merge after login. | browser-001 |
Authorization | header | string | Optional | Bearer token returned by POST /auth/login. | Bearer <token> |
JSON request body
| Name | Location | Type | Required | Description | Example |
|---|---|---|---|---|---|
code | body | string | Required | Case-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 history
Returns orders for the authenticated customer in the selected test run, newest first.
Parameters and headers
| Name | Location | Type | Required | Description | Example |
|---|---|---|---|---|---|
X-Test-Run-Id | header | string | Optional | Isolates state for one automation execution; defaults to shared-demo. | poc-run-001 |
Authorization | header | string | Required | Bearer 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 order
Checks delivery fields, current inventory and price snapshots, then creates one idempotent order and clears the cart.
Parameters and headers
| Name | Location | Type | Required | Description | Example |
|---|---|---|---|---|---|
X-Test-Run-Id | header | string | Optional | Isolates state for one automation execution; defaults to shared-demo. | poc-run-001 |
Authorization | header | string | Required | Bearer token returned by POST /auth/login. | Bearer <token> |
Idempotency-Key | header | string | Optional | Returns the existing order when the same value is retried in one run. | checkout-001 |
JSON request body
| Name | Location | Type | Required | Description | Example |
|---|---|---|---|---|---|
address | body | string | Required | Synthetic street address. | 10 Test Avenue |
city | body | string | Required | Delivery city. | Boston |
postal | body | string | Required | Postal 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 order
Cancels an authenticated customer's order and restores its inventory. Repeating a successful cancellation is idempotent.
Parameters and headers
| Name | Location | Type | Required | Description | Example |
|---|---|---|---|---|---|
X-Test-Run-Id | header | string | Optional | Isolates state for one automation execution; defaults to shared-demo. | poc-run-001 |
Authorization | header | string | Required | Bearer token returned by POST /auth/login. | Bearer <token> |
id | path | string | Required | BookNest 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 packs
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
| Name | Location | Type | Required | Description | Example |
|---|---|---|---|---|---|
X-Test-Defects | header | string (comma-separated enum) | Optional | Activates deterministic intentional defects. Values: smoke, ui, functional, validation, api, state. The equivalent defects query parameter is also supported. | api,state |
defects | query | string (comma-separated enum) | Optional | Alternative 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 state
Returns the selected run's active scenario and settings, plus every scenario's editable parameter metadata, defaults, types and limits.
Parameters and headers
| Name | Location | Type | Required | Description | Example |
|---|---|---|---|---|---|
X-Test-Run-Id | header | string | Optional | Isolates state for one automation execution; defaults to shared-demo. | poc-run-001 |
X-Test-Admin-Key | header | string | Required | Protected 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 scenario
Sets one deterministic failure or data mode and resets its request counter for the selected run.
Parameters and headers
| Name | Location | Type | Required | Description | Example |
|---|---|---|---|---|---|
X-Test-Run-Id | header | string | Optional | Isolates state for one automation execution; defaults to shared-demo. | poc-run-001 |
X-Test-Admin-Key | header | string | Required | Protected deployment secret for scenario and reset operations. | <test-admin-key> |
JSON request body
| Name | Location | Type | Required | Description | Example |
|---|---|---|---|---|---|
scenario | body | string enum | Required | normal, 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 |
settings | body | object | Optional | Scenario-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 run
Deletes users, sessions, carts, inventory overrides, orders and scenario state only for the selected run.
Parameters and headers
| Name | Location | Type | Required | Description | Example |
|---|---|---|---|---|---|
X-Test-Run-Id | header | string | Optional | Isolates state for one automation execution; defaults to shared-demo. | poc-run-001 |
X-Test-Admin-Key | header | string | Required | Protected 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"
}