---
description: Explanation of HTTP status codes used, when to use them, etc.
---

# Status Codes

<details>

<summary>GENERAL</summary>

* **200 OK**: Successful GET/PUT/POST (anything successful)
* ~~**201 Created**: Resource successfully created.~~
* **204 No Content**: Successful DELETE.
* **400 Bad Request**: General error for malformed requests.
* **401 Unauthorized**: Authentication error. Or Unauthenticated user
* **403 Forbidden:** User is logged in, but doesn't have correct permissions
* **404 Not Found:** Content / Route not found
* **402 Payment Required:** User's free trial expired and they do not have a paid subscription
* **426 Upgrade Required:** User has a paid account, but does not have access to the feature
* _... (continue with other codes; reorganize how you wish; add more detail)_

</details>

<details>

<summary>Front End Usage (mocking responses via Storybook)</summary>

`_mock.ts // src/api/_mock.ts)`

```typescript
export const STATUS_CODE = {
  SUCCESS: 200, // any successful CRUD operation
  BAD_REQUEST: 400, // e.g. trying to deactivate resource that is in use by another resource (e.g. note/file category), ...
  UNAUTHORIZED: 401, // aka unauthenticated (authentication/logged in check)
  FORBIDDEN: 403, // e.g. restricted permissions
  NOT_FOUND: 404, // e.g. another company's resource, a resource a user doesn't have access to, etc.
  UNPROCESSABLE_ENTITY: 422, // RecordInvalid / NotNullViolation (e.g. trying to create a record with the wrong fields, or a null field that is required)
  UPGRADE_REQUIRED: 426, // e.g. trying to access a feature that is not available in the current plan
  PAYMENT_REQUIRED: 402, // e.g. company trial has expired
  INTERNAL_SERVER_ERROR: 500, // "Something went wrong."
  // not actually used in BE, but here as "catch-all" for not-yet-handled (or not allowed) methods
  METHOD_NOT_ALLOWED: 405, // "Method Not Allowed"
};
```

</details>

### TABLE

<table><thead><tr><th width="114">Request Type</th><th width="133">Route</th><th width="146">Condition</th><th width="141">Status Code</th><th>Status Text</th><th>Message / Reason</th></tr></thead><tbody><tr><td>GET</td><td>/resource</td><td>Successful</td><td>200</td><td>OK</td><td>Data is successfully retrieved.</td></tr><tr><td>GET</td><td>/resource/:id</td><td>Record not found</td><td>404</td><td>Not Found</td><td>"Resource record not found"</td></tr><tr><td>GET</td><td>/resource/:id</td><td>Successful</td><td>200</td><td>OK</td><td>Data is successfully retrieved.</td></tr><tr><td>POST</td><td>/resource</td><td>ForbiddenError (Creation not allowed)</td><td>403</td><td>Forbidden</td><td>"You are not authorized to perform this action"</td></tr><tr><td>POST</td><td>/resource</td><td>Successful Creation</td><td>200</td><td>OK</td><td>Data is successfully created.</td></tr><tr><td>PUT</td><td>/resource/:id</td><td>ForbiddenError (Update not allowed)</td><td>403</td><td>Forbidden</td><td>"You are not authorized to perform this action"</td></tr><tr><td>PUT</td><td>resource/:id</td><td>Bad Request</td><td>400</td><td>Bad Request</td><td>"Cannot deactivate resource because it is in use by one or more other resources"</td></tr><tr><td>PUT</td><td>/resource/:id</td><td>Successful Update</td><td>200</td><td>OK</td><td>Data is successfully updated.</td></tr><tr><td>DELETE</td><td>/resource/:id</td><td>ForbiddenError (Deletion not allowed)</td><td>403</td><td>Forbidden</td><td>"You are not authorized to perform this action"</td></tr><tr><td>DELETE</td><td>/resource/:id</td><td>Bad Request</td><td>400</td><td>Bad Request</td><td>"Cannot delete resource because it is in use by one or more resources"</td></tr><tr><td>DELETE</td><td>/resource/:id</td><td>Successful Deletion</td><td>200</td><td>OK</td><td>Data is successfully deleted.</td></tr><tr><td>Any</td><td>Any</td><td>RecordInvalid</td><td>422</td><td>Unprocessable Entity</td><td>Specific model validation errors</td></tr><tr><td>Any</td><td>Any</td><td>NotNullViolation</td><td>422</td><td>Unprocessable Entity</td><td>Specific null violation message</td></tr><tr><td>Any</td><td>Any</td><td>UpgradeRequiredError</td><td>426</td><td>Upgrade Required</td><td>"Resource limit reached. Please upgrade your plan to add more"</td></tr><tr><td>Any</td><td>Any</td><td>PaymentRequired</td><td>402</td><td>Payment Required</td><td>"Your company trial has expired."</td></tr><tr><td>Any</td><td>Any</td><td>Not Authenticated</td><td>401</td><td>Unauthorized</td><td>"User not found, Please log out and log back in."</td></tr><tr><td>Any</td><td>Any</td><td>InternalServerError</td><td>500</td><td>Internal Server Error</td><td>"Something went wrong."</td></tr></tbody></table>

**Notes:**

* This table was created largely based on (1) `api_controller.rb` and (2) `note_categories_controller.rb`
* The "Any" errors (`RecordNotFound`, `RecordInvalid`, `NotNullViolation, etc.)` are generic error handlers that could be triggered on any type of request (GET, POST, PUT, DELETE) if the corresponding exception is raised.
* The `ForbiddenError` is raised when the user does not have the necessary roles to perform create, update, or delete actions.
* The condition "Successful" implies that the operation completed without triggering any of the exceptions handled in the `ApiController`.

\
