Building REST APIs

HTTP Status Codes

ReadingPreview

আপনি একটি free preview lesson দেখছেন।

আমরা এখন পর্যন্ত define করেছি:

HTTP endpoints

Controllers / Handlers

Request DTOs

Response DTOs

এখন আরেকটি গুরুত্বপূর্ণ contract দরকার:

Request সফল বা ব্যর্থ হলে client কীভাবে বুঝবে কী ঘটেছে?

এর প্রথম signal হলো:

HTTP status code

For example:

201 Created

বা:

404 Not Found

বা:

409 Conflict

Status code API client-কে response body parse করার আগেই broad outcome communicate করে।

এই lesson-এর goal:

আমাদের Product, Inventory, এবং Order APIs-এর expected outcomes-কে consistent HTTP status semantics-এ map করা।


Status Code Is Part of the API Contract

ধরুন client call করে:

GET /orders/O-1001

Response body:

{
  "id": "O-1001",
  "status": "UNPAID"
}

কিন্তু status:

500 Internal Server Error

হলে body যত ভালোই হোক, contract contradictory।

Similarly:

200 OK

with:

{
  "error": "Order not found"
}

also weak design।

Status code এবং response body একসঙ্গে একই outcome communicate করা উচিত।


Broad Status Families

HTTP status codes broadly grouped:

2xx
→ success

4xx
→ request/client/context prevents operation

5xx
→ server failed unexpectedly or infrastructure failed

আমাদের current API-তে primarily এই তিন family গুরুত্বপূর্ণ।


200 OK

200 OK means request successfully processed এবং response body আছে বা থাকতে পারে।

Typical read:

GET /products/P-100

Success:

200 OK

with:

{
  "id": "P-100",
  "name": "Keyboard",
  "price": 100.00
}

Collection Reads

For:

GET /products

or:

GET /orders

successful response normally:

200 OK

even if collection is empty।

Example:

{
  "items": []
}

or whatever pagination response shape we later define।

Empty result is not automatically:

404

because the collection resource exists; it just currently contains no matching items।


201 Created

201 Created is appropriate when request successfully creates a new resource।

Examples:

POST /products

and:

POST /orders

On successful creation:

201 Created

This is more precise than generic:

200 OK

because it communicates:

A new resource now exists.


Location With 201

Creation may also return:

Location: /orders/O-1001

This identifies the newly created resource।

Conceptually:

POST /orders
    ↓
201 Created
Location: /orders/O-1001

Useful and conventional।


204 No Content

204 No Content means:

operation succeeded

no response body

For example, an update endpoint could return:

204 No Content

if client doesn't need updated representation।

But remember:

A 204 response must not be treated as if it also contains normal JSON content.


Do We Need 204 Everywhere?

No।

For important business operations such as:

cancel Order

update Product

set Inventory

returning the resulting representation using:

200 OK

may be more useful।

For example:

POST /orders/O-1001/cancel

could return:

200 OK

with:

{
  "id": "O-1001",
  "status": "CANCELLED",
  ...
}

That gives client the confirmed final state।


Success Status Should Match Observable Outcome

Useful guideline:

resource created
→ 201

successful read/update with body
→ 200

successful operation intentionally without body
→ 204

Do not choose status purely from habit।


400 Bad Request

400 Bad Request fits requests that fail the API input contract।

Examples:

malformed JSON

missing required request field

invalid field format

quantity has an invalid basic value

invalid path identifier representation

For example:

POST /orders

with:

{
  "items": null
}

may result in:

400 Bad Request

Transport Validation vs Business Conflict

Important distinction:

Suppose request:

{
  "items": [
    {
      "productId": "P-100",
      "quantity": -5
    }
  ]
}

This clearly fails request validation।

400 is a natural fit।

But suppose quantity is valid:

quantity = 5

while Inventory has:

2

Now request shape is valid।

The operation fails because current business state cannot satisfy it।

That is a different category।


Don't Use 400 for Everything

A weak API maps every expected failure to:

400 Bad Request

Examples:

Order missing
→ 400

Product missing
→ 400

not authenticated
→ 400

not authorized
→ 400

Order already paid
→ 400

This throws away useful semantics।

Clients then have to parse strings to understand what happened।


401 Unauthorized

Despite the confusing name, 401 is primarily about authentication।

Use it when the server cannot establish a valid authenticated caller।

Examples:

missing authentication credential

invalid credential

expired/unacceptable token

Conceptually:

Request
    ↓
Authentication
    ↓
identity not established
    ↓
401

Authentication Happens Before the UseCase

Suppose:

POST /orders

requires authenticated customer identity।

If token is invalid, we should not execute:

CreateOrderUseCase

and then discover customer is missing।

Security boundary rejects request first:

401 Unauthorized

403 Forbidden

403 Forbidden means:

caller is authenticated

but not permitted to perform this operation

Example:

CUSTOMER

attempts:

POST /products

which is admin-only।

Response:

403 Forbidden

is appropriate।


401 vs 403

A useful mental model:

401
→ Who are you? Valid authentication not established.
403
→ We know who you are, but you cannot do this.

Keep those semantics distinct।


Ownership Is More Nuanced

Suppose authenticated customer A requests:

GET /orders/O-2000

but the Order belongs to customer B।

We could return:

403 Forbidden

because A is not authorized।

But this reveals:

Order O-2000 exists.

For customer-owned resources, that may be undesirable।


404 for Hidden Ownership

A common security-oriented approach is:

not found
OR
not visible to this customer

both become:

404 Not Found

Then client cannot distinguish:

resource genuinely absent

from:

resource exists but belongs to someone else

For customer Order access, this is a reasonable v1 direction।


404 Not Found

404 fits when requested resource cannot be found within the caller's accessible resource scope।

Examples:

GET /products/P-999

if Product does not exist or isn't visible according to that endpoint contract।

GET /orders/O-999

if no accessible Order exists।


404 for Mutations Too

404 is not only for GET।

For example:

POST /orders/O-999/cancel

if the accessible Order does not exist:

404 Not Found

is appropriate।

Similarly:

PATCH /products/P-999

for admin could return:

404 Not Found

409 Conflict

409 Conflict is useful when request is structurally valid but conflicts with current resource state or business state।

Our Order lifecycle provides good examples।

Suppose:

Order = PAID

Client requests:

POST /orders/O-1001/cancel

Request itself is well-formed।

Order exists।

Caller owns it।

But lifecycle says:

PAID → CANCELLED

is invalid।

A natural response:

409 Conflict

Another 409 Example

Suppose Order is already:

CANCELLED

and client tries:

POST /orders/O-1001/pay

This conflicts with the current Order state।

Again:

409 Conflict

is a reasonable mapping।


Insufficient Inventory

Suppose client requests:

10 units

but available Inventory is:

3 units

The request shape is valid।

Product exists।

But current application state cannot satisfy it।

This can reasonably map to:

409 Conflict

because the requested operation conflicts with current Inventory state।


Product Inactive

Suppose customer creates an Order containing:

Product P-100

but Product is inactive।

Again:

request structure valid

Product exists

current state does not allow ordering

A conflict-style response is reasonable।

We can map such business-state failures consistently through our error model।


Duplicate Product Lines

What about:

{
  "items": [
    {
      "productId": "P-100",
      "quantity": 1
    },
    {
      "productId": "P-100",
      "quantity": 2
    }
  ]
}

Our contract explicitly says duplicate Product lines are invalid input։

This is more naturally:

400 Bad Request

than 409, because the submitted request structure itself violates the create-order contract independent of current server state।

This distinction is useful:

invalid request composition
→ 400

valid request conflicts with current business state
→ 409

Product Not Found During Order Creation

Suppose request contains:

P-999

which does not exist।

Possible mappings include:

404

or a request-level business error depending on API design।

For our API, treating referenced missing resources as:

404 Not Found

is reasonable and clear։

The error body can specify which Product reference could not be resolved।


Referenced Resource vs Primary Resource

There is nuance।

Request:

POST /orders

is not itself requesting:

/products/P-999

but the operation references Product P-999।

Still, 404 can communicate:

A resource required by this operation does not exist.

The important thing is consistent documentation।


422 Unprocessable Content?

You may encounter APIs using:

422 Unprocessable Content

for requests that are syntactically valid but semantically invalid।

For example:

quantity <= 0

duplicate Product lines

business validation failures

This can be a valid API style।

But our goal is not to use every available status code।

For this course, a simpler mapping is enough:

malformed/invalid request
→ 400

resource absent
→ 404

current-state conflict
→ 409

This keeps the contract easy to understand।


Don't Debate 400 vs 422 Forever

Teams often spend excessive time debating whether a validation failure should be:

400

or:

422

What matters more:

consistent convention

structured error code

clear documentation

predictable behaviour

A perfectly consistent 400 strategy is often better than random mixtures of 400/409/422 across endpoints।


405 Method Not Allowed

Suppose endpoint supports:

GET /products/P-100

but client sends:

DELETE /products/P-100

and no DELETE mapping exists।

Spring may respond:

405 Method Not Allowed

This is typically framework-level behaviour։

Our Handler doesn't need custom domain logic for it।


415 Unsupported Media Type

If endpoint expects JSON:

Content-Type: application/json

but client sends unsupported content type, framework may return:

415 Unsupported Media Type

Again, primarily transport/framework concern।

We do not manually handle this in every Controller।


5xx Server Errors

5xx should represent unexpected server/infrastructure failures։

Examples:

database unavailable

unexpected NullPointerException

unhandled programming bug

unexpected internal infrastructure failure

For example:

500 Internal Server Error

may be returned for an unexpected exception।


Business Rejection Is Not 500

Suppose:

order.cancel();

throws because Order is already PAID।

This is an expected business rejection։

It should not automatically become:

500 Internal Server Error

just because Java represented it with an exception।

The error mapping layer must distinguish:

expected application/domain failure

from:

unexpected system failure

Payment Provider Failure

Payment introduces more nuance।

Suppose:

PaymentService

calls provider and provider returns a known payment rejection։

That may be an expected business/integration result, not a 500

But if provider is unavailable due infrastructure failure, we may need a 5xx response such as:

502 Bad Gateway

or:

503 Service Unavailable

depending on the exact failure semantics।

We will design this more carefully in Module 9 when provider behaviour is known।


502 Bad Gateway

For a backend acting as a server to clients and a client to another upstream system, 502 can represent:

The upstream system returned an invalid/unusable failure while handling this request.

It can be relevant for external integrations։

But don't introduce detailed mappings before we know the actual provider contract।


503 Service Unavailable

503 can represent:

service temporarily unable to handle request

For example due to:

dependency unavailable

temporary overload

maintenance

Again, operational policies and retry semantics matter।

We will not use it casually for every exception।


500 Internal Server Error

500 is the generic fallback for unexpected application failure।

Example:

programming bug

unclassified runtime failure

Client should receive a safe error response without:

stack trace

SQL statement

Java internals

while logs retain enough information for engineers to investigate।


Status Code Should Not Leak Internal Architecture

Suppose PostgreSQL throws:

constraint violation

That does not mean client should receive raw database exception semantics։

The application asks:

What does this failure mean at the API boundary?

If it's due to an expected conflict:

409

may be appropriate।

If it indicates an unexpected implementation problem:

500

may be appropriate।

Translate meaning, not exception class names।


Product Endpoint Statuses

Let's define current direction։

GET /products

Success:

200 OK

Even if result is empty।


GET /products/{productId}

Accessible Product exists:

200 OK

Not found/not visible according to endpoint contract:

404 Not Found

POST /products

Valid admin request, Product created:

201 Created

Invalid request:

400 Bad Request

Unauthenticated:

401 Unauthorized

Authenticated but not admin:

403 Forbidden

PATCH /products/{productId}

Success:

200 OK

with updated representation।

Invalid update payload:

400 Bad Request

Product missing:

404 Not Found

Not permitted:

403 Forbidden

POST /products/{productId}/deactivate

Success:

200 OK

Product missing:

404 Not Found

Unauthorized role:

403 Forbidden

If future requirements make repeated deactivation an invalid operation, that could become:

409 Conflict

But our current Product model treats repeated deactivation as harmless/idempotent, so we should not invent a conflict yet।


Inventory Endpoint Statuses

GET /inventory

Admin success:

200 OK

Non-admin:

403 Forbidden

GET /inventory/{productId}

Inventory exists:

200 OK

No Inventory/Product resource:

404 Not Found

PUT /inventory/{productId}

Valid quantity update:

200 OK

or 204 if we intentionally return no body।

For this course, returning updated Inventory representation with 200 is useful।

Negative quantity:

400 Bad Request

Target Product/Inventory not found:

404 Not Found

Customer without admin permission:

403 Forbidden

Order Endpoint Statuses

Now the most important API։


POST /orders

Success:

201 Created

Invalid body:

no items

negative/zero quantity

duplicate Product lines

malformed input

400 Bad Request

Missing Product During Order Creation

Example:

P-999 does not exist

A reasonable response:

404 Not Found

Error body can identify the missing required Product reference։


Inactive Product

Product exists but cannot participate in new Order։

This is current-state conflict:

409 Conflict

Insufficient Inventory

Request is valid, but current Inventory cannot satisfy it:

409 Conflict

This communicates:

Retry may become possible if business state changes.


GET /orders

Authenticated customer success:

200 OK

No Orders:

200 OK

with empty collection।

Missing/invalid authentication:

401 Unauthorized

GET /orders/{orderId}

Own accessible Order:

200 OK

No accessible Order:

404 Not Found

This can intentionally cover:

does not exist

and:

belongs to another customer

for customer-facing access if we choose existence-hiding behaviour।


POST /orders/{orderId}/cancel

Eligible own UNPAID Order:

200 OK

with resulting:

CANCELLED

representation।

No accessible Order:

404 Not Found

PAID Order:

409 Conflict

Already CANCELLED Order:

409 Conflict

Unauthenticated:

401 Unauthorized

POST /orders/{orderId}/pay

Eligible own UNPAID Order + successful provider payment:

200 OK

with:

status = PAID

No accessible Order:

404 Not Found

Already PAID:

409 Conflict

CANCELLED:

409 Conflict

Authentication missing:

401 Unauthorized

Provider-specific failure mapping is deferred until we understand the Payment Service contract।


Why Not 400 for Already Paid?

Because the HTTP request is structurally valid।

The conflict is:

current Order state

Therefore:

409 Conflict

communicates the situation better।


Why Not 404 for Inactive Product?

The Product does exist।

The problem is:

it is not currently valid for this operation

So:

409 Conflict

is more expressive than pretending it doesn't exist—

unless the specific customer-facing API intentionally hides inactive Products entirely।

Context matters։


Endpoint Context Can Change the Meaning

Example:

GET /products/P-100

if inactive Products are intentionally invisible to customers, customer-facing read may return:

404 Not Found

But during:

POST /orders

if Product reference was valid but state changed between browse and creation, returning:

409 Conflict

can communicate:

This Product can no longer be ordered.

Same underlying Product state can produce different API semantics depending on operation।


Status Mapping Should Be Centralized

We do not want every Handler to contain:

catch (ProductNotFoundException ex) {
    return ResponseEntity.notFound().build();
}

and similar blocks repeatedly।

Instead, expected application/domain errors should be translated in one consistent place।

In Spring, this is commonly implemented with:

@ControllerAdvice

@ExceptionHandler

We will cover consistent error responses later in this module।


Domain Error Does Not Carry HTTP Status

Avoid:

public class OrderNotCancellableException
        extends RuntimeException {

    private final int statusCode = 409;
}

Domain should express business meaning:

Order cannot be cancelled.

HTTP layer decides:

409 Conflict

This keeps domain transport-independent।


UseCase Should Not Return HTTP Codes

Avoid:

public int execute(...) {
    return 404;
}

or:

return HttpStatus.CONFLICT;

Application operation should return:

result

or raise/represent an application/business failure।

Handler/error mapping owns HTTP translation।


Avoid 200 With success=false

Weak:

200 OK
{
  "success": false,
  "error": "Insufficient inventory"
}

Now HTTP layer says:

success

while body says:

failure

Use:

409 Conflict

plus structured error body।


Avoid Error Strings as the Only Contract

Weak:

{
  "message": "Something went wrong"
}

Clients need stable machine-readable information。

Later our error response will likely include a stable error identifier such as:

INSUFFICIENT_INVENTORY

alongside human-readable message।

Status code gives broad HTTP category।

Error code gives application-specific meaning।


Status Code vs Error Code

Example:

409 Conflict

could represent several business conflicts:

ORDER_ALREADY_PAID

ORDER_ALREADY_CANCELLED

INSUFFICIENT_INVENTORY

PRODUCT_NOT_ORDERABLE

So status code alone is intentionally broad।

Structured error body gives specific application meaning।


Don't Encode Business Meaning Only in Status

We should not invent:

one unique HTTP status per domain error

HTTP has a finite standard vocabulary।

Use:

HTTP status
+
application error code

for precision।


Empty Collection vs Missing Resource

Important distinction:

GET /orders

no Orders:

200 OK

empty collection।

But:

GET /orders/O-999

no Order:

404 Not Found

Collection absence and item absence are different semantics।


Update of Missing Resource

Suppose:

PATCH /products/P-999

Body is valid, but Product doesn't exist।

Return:

404 Not Found

Do not silently create the Product unless endpoint contract explicitly defines upsert behaviour।

Our PATCH does not।


PUT Does Not Automatically Mean Upsert

HTTP PUT can sometimes support creation at a client-chosen URI।

But our:

PUT /inventory/{productId}

does not need to mean:

Create Inventory for any arbitrary Product ID.

Our product/application contract can require the Product/Inventory target to exist।

If not:

404 Not Found

Method semantics do not override application rules।


Concurrency Conflicts

Later, if persistence uses optimistic concurrency and two updates conflict, an application may map the resulting conflict to:

409 Conflict

depending on API design։

But we have not selected our exact concurrency strategy yet।

Don't expose version/concurrency error contracts prematurely।


Database Constraint Violations

Suppose a database constraint prevents:

negative Inventory

If this represents a normal expected user/business conflict, translate it into an application-level error where possible।

Do not return raw:

SQLState

constraint name

to client։

Database constraint is a final integrity guard, not public API vocabulary।


Status Codes and Logging

Expected:

400

404

409

are often not production incidents by themselves։

For example customer requesting an old Order ID may legitimately get 404

Unexpected:

500

is more operationally significant।

Later observability can distinguish:

client/business failures

server failures

rather than treating all non-2xx responses equally।


Status Codes and Metrics

A useful production metric may group responses by:

2xx

4xx

5xx

But high 409 during checkout might still indicate a business/Inventory issue worth investigating।

HTTP status provides useful dimensions, but operational meaning comes from context and application error codes too।


Do Not Hide Bugs as 400

A dangerous pattern:

catch (Exception ex) {
    return badRequest();
}

Now:

NullPointerException

database failure

programming bug

all become:

400 Bad Request

This misleads clients and hides production failures।

Only known request/application errors should become controlled 4xx responses।

Unexpected exception → safe 5xx response + internal logging।


Do Not Hide Dependency Failures as 409

Likewise, if PostgreSQL is unavailable, response should not say:

409 Conflict

just because Order creation couldn't complete।

The request did not conflict with business state।

The system failed to execute it।

That's a server/infrastructure failure।


A Practical Mapping Table

For our current API, a useful baseline:

SituationHTTP Status
Successful read200 OK
Successful update with response200 OK
New resource created201 Created
Success with intentionally no body204 No Content
Malformed/invalid request400 Bad Request
Authentication not established401 Unauthorized
Authenticated but role not permitted403 Forbidden
Resource not found/not visible404 Not Found
Valid request conflicts with current business state409 Conflict
Unexpected application failure500 Internal Server Error

This is our simple v1 foundation।


Product Examples

POST /products
valid admin request
→ 201
POST /products
negative price
→ 400
POST /products
CUSTOMER role
→ 403
PATCH /products/P-999
→ 404

Inventory Examples

PUT /inventory/P-100
quantity = 20
→ 200
PUT /inventory/P-100
quantity = -5
→ 400
PUT /inventory/P-999
target unavailable
→ 404

Order Examples

POST /orders
valid
→ 201
POST /orders
empty items
→ 400
POST /orders
duplicate Product lines
→ 400
POST /orders
Product missing
→ 404
POST /orders
Product inactive
→ 409
POST /orders
Inventory insufficient
→ 409

Order Lifecycle Examples

POST /orders/O-1/cancel
UNPAID own Order
→ 200
POST /orders/O-1/cancel
PAID Order
→ 409
POST /orders/O-1/cancel
already CANCELLED
→ 409
POST /orders/O-1/pay
CANCELLED Order
→ 409
GET /orders/O-1
not accessible to current customer
→ 404

Status Codes Should Be Predictable Across Endpoints

If missing Product means:

404

in one endpoint, avoid mapping similar missing resource situations to:

400

elsewhere without a reason।

If invalid body means:

400

keep that convention consistent।

API predictability reduces client-side special cases।


A Client Should Be Able to Reason Broadly

Client can interpret:

2xx
→ operation succeeded

400
→ fix request input

401
→ establish authentication

403
→ current identity lacks permission

404
→ requested accessible resource unavailable

409
→ refresh/reconsider current business state

5xx
→ server/dependency problem

Application error codes then give precise details।

This is a strong, simple contract।


Common Mistake 1 — Everything Is 200

Clients cannot rely on HTTP semantics।


Common Mistake 2 — Everything Is 400

Malformed requests, missing resources, auth failures, and business conflicts become indistinguishable।


Common Mistake 3 — Every Exception Is 500

Expected domain/application rejections become server failures।


Common Mistake 4 — 401 and 403 Used Interchangeably

Authentication and authorization mean different things।


Common Mistake 5 — Empty Collection Returns 404

An empty collection is usually a valid successful collection response।


Common Mistake 6 — Client-Side Business Conflict Returns 500

For example paid Order cancellation is an expected 4xx business rejection।


Common Mistake 7 — Database Error Leaks Directly

Clients should receive application/API meaning, not SQL implementation details।


Common Mistake 8 — Status Code Encoded in Domain Exception

Domain should remain HTTP-independent।


Common Mistake 9 — Timeout Automatically Means Client Error

Infrastructure/network failure needs its own semantics; it is not automatically 400 or 409


Common Mistake 10 — Too Many Status Codes Without Consistency

More nuanced does not automatically mean better।

A small predictable status vocabulary is often easier to integrate with।


Status Code Review Checklist

For each API failure, ask:

Did the request fail basic input/transport validation?
→ 400

Was authentication not established?
→ 401

Is the authenticated caller not permitted by role?
→ 403

Is the required accessible resource missing?
→ 404

Is the request valid but current business state
does not permit the operation?
→ 409

Did our application/infrastructure fail unexpectedly?
→ 5xx

For success:

Was a resource created?
→ 201

Is this a normal successful response with body?
→ 200

Is success intentionally body-less?
→ 204

Keep HTTP Mapping at the Edge

Our flow remains:

Domain / UseCase failure
        ↓
HTTP error mapping
        ↓
status code + error body

Not:

Order
→ knows 409

or:

Product
→ throws 404

This preserves transport independence।


Engineering Principle

The core principle:

HTTP status codes describe the category of observable outcome; domain and application errors describe the business meaning behind that outcome.

Another:

Use 4xx for expected request/auth/business failures, and reserve 5xx for genuine server or infrastructure failures.

And:

Consistency is more valuable than using the largest possible vocabulary of HTTP status codes.


Summary

In this lesson, we learned that:

  • HTTP status codes are part of the public API contract.
  • 200 OK fits successful reads and updates that return a body.
  • Empty collection reads should normally still return 200.
  • 201 Created fits successful Product and Order creation.
  • 204 No Content is useful only when success intentionally has no response body.
  • 400 Bad Request fits malformed or invalid request input.
  • 401 Unauthorized means valid authentication was not established.
  • 403 Forbidden means the caller is authenticated but lacks permission.
  • Customer-owned resource existence can be hidden by returning 404 for both missing and inaccessible resources.
  • 404 Not Found also applies to mutations targeting missing resources.
  • 409 Conflict fits valid requests that cannot proceed because of current business state.
  • PAID Order cancellation, CANCELLED Order payment, inactive Product ordering, and insufficient Inventory are natural conflict cases.
  • Duplicate Product lines are better treated as invalid request input than current-state conflict.
  • Expected application/domain failures should not become 500.
  • Unexpected application or infrastructure failures should result in safe 5xx responses.
  • External Payment Provider failure semantics will be defined later from the actual integration contract.
  • Status codes should remain broad while structured application error codes provide precise business meaning.
  • Domain objects and UseCases should not know HTTP status codes.
  • HTTP error translation should be centralized rather than repeated in every Handler.
  • A small, consistent status vocabulary is preferable to ad hoc status selection.

Next lesson:

Request Validation

There we will add validation to our Product, Inventory, and Order request DTOs using Spring/Jakarta Bean Validation, distinguish transport validation from domain invariants, and decide exactly where checks such as required fields, positive quantity, duplicate Products, Product existence, and Inventory availability belong.