# HTTP Methods & Status Codes

### Response Codes

This section will describe the circumstances when you would return each possible HTTP status code that our endpoints typically respond with.

{% hint style="info" %}
The examples below only briefly specify which types of URI paths and parameters are required to generate the responses described here.

Please see the [Routing and Parameters](https://docs.elentra.org/api/elentra-api-standards/routing-and-parameters) sections for specific details on the structure of URI paths and query parameters.
{% endhint %}

## This section contains the API standards and guidelines when implementing a GET route

<mark style="color:blue;">`GET`</mark> `/api/v2`

The available response codes for a GET are listed below the header "Responses"\
Expand the response code to see the guidelines and standards. &#x20;

#### Query Parameters

| Name | Type   | Description      |
| ---- | ------ | ---------------- |
| \*   | String | Query parameters |

#### Headers

| Name                                            | Type   | Description  |
| ----------------------------------------------- | ------ | ------------ |
| Authorization<mark style="color:red;">\*</mark> | String | Bearer token |

{% tabs %}
{% tab title="200: OK Request has succeeded" %}
The request was successful.&#x20;
{% endtab %}

{% tab title="204: No Content Response body is empty" %}
The status code `204 No Content` does not apply to GET requests. If required, then consider using the `HEAD` or `OPTIONS` verbs instead.
{% endtab %}

{% tab title="400: Bad Request Validation of request failed" %}
When request validation fails, 400 Bad Request status code is returned to the client.

**Requirements**&#x20;

The response messaging should be clear and concise.

**Scenario**

&#x20;`400` may be returned if the query parameters of a `GET` request is invalid or missing.
{% endtab %}

{% tab title="401: Unauthorized User is not authenticated" %}
This status code is returned to the client when the user is unauthenticated or the token has expired.
{% endtab %}

{% tab title="403: Forbidden User does not have permission" %}
This status code is returned to the client when the user does not have permission to access the requested resource according to their ACL Role / Group.

**No data** should be returned if the user does not have permission.
{% endtab %}

{% tab title="404: Not Found Requested resource was not found" %}
This response code should be returned when the requested resource is not found.

**Requirements**

1\. An empty collection should not return a `404` but a `200`.

2\. Any invalid URI with a non-existing resource identified in the URI will return a `404`.

3\. If a resource doesn't exist but is associated with the requested resource that *does* exist, then we should not send  `404` as a response. For example, a course has been deleted, but the framework still exists.

4\. If an internal dependency related to the resource being requested cannot be resolved, respond with `500`.

**Scenarios**

1\. The path contains a resource that doesn't exist i.e. `/framework/1/tags` where Framework 1 doesn't exist.

2\. The endpoint needs to fetch data to retrieve the requested resource `/courses/1/frameworks/1`. If course 1 does not exist, we should return `404` since the course is in the path.
{% endtab %}

{% tab title="500: Internal Server Error Internal error not caused by user" %}
The client's request was valid, but the application had an issue. The user has no control over resolving the error.

**Requirements**

1\. Error message should contain:

&#x20;   • Context of the issue

2\. Error message should not contain:

&#x20;   • Leaked Data

&#x20;   • Stack Trace

&#x20;   • Responding with an SQL query that failed

3\. Don't use `500` as a catch-all exception for other types of errors:

&#x20;   • Utilize `404` for not found resources

&#x20;   • Or other applicable `4xx` response codes for client errors

4\. When responding with `500`, the error should be considered a bug. Therefore, it should be investigated and resolved so the client does not experience this again.

5\. If an internal dependency related to the resource has not been found for the retrieval of any resource in the URI, we should respond with `500` instead.

**Logging**

Log detailed information on the server to allow technical personnel to debug and determine the cause of the error.

**Scenario**

When saving an entity that has a relationship that cannot be resolved, respond with `500`.
{% endtab %}
{% endtabs %}

## This section contains the API standards and guidelines when implementing a POST route

<mark style="color:green;">`POST`</mark> `/api/v2`

The available response codes for a POST are listed below the header "Responses"\
Expand the response code to see the guidelines and standards. &#x20;

#### Headers

| Name                                            | Type   | Description  |
| ----------------------------------------------- | ------ | ------------ |
| Authorization<mark style="color:red;">\*</mark> | String | Bearer token |

#### Request Body

| Name  | Type   | Description        |
| ----- | ------ | ------------------ |
| \*    | String | Request parameters |
| {...} | String | JSON request body  |

{% tabs %}
{% tab title="200: OK Request has succeeded" %}
The request was successful.&#x20;
{% endtab %}

{% tab title="201: Created Resource has been created" %}
The resource was created successfully.

This is the most common status code for `POST`. The body of the response should contain the newly created object.

**Best practice**

Set the location header to the URI of the new resource.
{% endtab %}

{% tab title="202: Accepted Request has been queued for processing" %}
The `202 Accepted` status code means that we will process the request in a:

&#x20; • Queue

&#x20; • Cron job

&#x20; • Schedule

**Suggestion**&#x20;

The response body may be empty with the relevant information set in the headers.
{% endtab %}

{% tab title="204: No Content Response body is empty" %}
When responding with `204`, the body **must be empty**.

**Best practice**

Set the location header to the URI of the new resource.
{% endtab %}

{% tab title="400: Bad Request Validation of request failed" %}
When request validation fails, `400` Bad Request status code is returned to the client.  \
\
**Requirements**&#x20;

The response messaging should be clear and concise.

**Scenario**&#x20;

`400` may return if the JSON, form submission data, query parameters, or file upload, is invalid or missing in the request body. Query parameters are uncommon for `POST` requests.
{% endtab %}

{% tab title="404: Not Found Requested resource was not found" %}
The `404 Not Found` response code should be returned when the requested resource is not found.

**Requirements**

1\. Posting to a non-existing collection should return a `404`

2\. Any invalid URI with a non-existing resource identified by the URI will return a `404`

3\. If an internal dependency related to the resource being requested cannot be resolved, respond with `500`.

**Scenarios**

1\. `POST /courses/1/frameworks`

If course 1 does not exist then return 404 should be returned to the client because the URI has a hierarchical dependency on the course.

2\. `POST /courses/1/frameworks/1`

Return 404 due to it being a non-existent POST URI. This should be put instead of `POST`.

3\. `POST /courses/1/frameworks/add`

POST to the framework collection directly. <br>

**Requirement**:

Use HTTP Verbs with RESTful resource paths.

***Avoid using verbs in the URI.***
{% endtab %}

{% tab title="403: Forbidden User does not have permission" %}
This status code is returned to the client when the user does not have permission to access the requested resource according to their ACL Role / Group.

**No data** should be returned if the user does not have permission.
{% endtab %}

{% tab title="409: Conflict Conflict in state while processing request" %}
The `409 Conflict` status code is returned when there is a conflict while saving a resource, which might prevent the application from processing the request.

**Scenarios**:

1\. A user already exists with the same email address or number.

2\. When a unique property is being saved, and the new value is a duplicate of the existing value.

3\. Anything that will violate data integrity e.g.  a foreign key violation.

4\. A violation of the state of dependent relationships to the object being saved.

5\. Uploading a file older than the existing one.
{% endtab %}

{% tab title="500: Internal Server Error Internal error not caused by user" %}
The client's request was valid, but the application had an issue. The user has no control over resolving the error.

**Requirements**

1\. Error message should contain:

&#x20;   • Context of the issue

2\. Error message should not contain:

&#x20;   • Leaked Data

&#x20;   • Stack Trace

&#x20;   • Responding with an SQL query that failed

3\. Don't use `500` as a catch-all exception for other types of errors:

&#x20;   • Utilize `404` for not found resources

&#x20;   • Or other applicable `4xx` response codes for client errors

4\. When responding with `500`, the error should be considered a bug. Therefore, it should be investigated and resolved so the client does not experience this again.

5\. If an internal dependency related to the resource being requested cannot be resolved, respond with `500`.

**Logging**

Log detailed information on the server to allow technical personnel to debug and determine the cause of the error.
{% endtab %}

{% tab title="401: Unauthorized User is not authenticated" %}
This status code is returned to the client when the user is unauthenticated or the token has expired.
{% endtab %}
{% endtabs %}

## This section contains the API standards and guidelines when implementing a PUT route

<mark style="color:orange;">`PUT`</mark> `/api/v2`

The available response codes for a PUT are listed below the header "Responses"\
Expand the response code to see the guidelines and standards. &#x20;

#### Headers

| Name                                            | Type   | Description  |
| ----------------------------------------------- | ------ | ------------ |
| Authorization<mark style="color:red;">\*</mark> | String | Bearer token |

#### Request Body

| Name  | Type   | Description        |
| ----- | ------ | ------------------ |
| \*    | String | Request parameters |
| {...} | String | JSON request body  |

{% tabs %}
{% tab title="200: OK Request has succeeded" %}
The request was successful.
{% endtab %}

{% tab title="201: Created Resource has been created" %}
The resource was created successfully.

This is a less common status code for `PUT`. The body of the response should contain the newly created object.

**Suggestion**

&#x20;A common practice is to set the location header to the URI of the newly created resource.
{% endtab %}

{% tab title="202: Accepted Request has been queued for processing" %}
The `202 Accepted` status code means that we will process the request in a:

&#x20; • Queue

&#x20; • Cron job

&#x20; • Schedule

The response body should be empty.

Relevant information should be set in the headers.

**Suggestion**&#x20;

The response body may be empty with the relevant information set in the headers.
{% endtab %}

{% tab title="204: No Content Response body is empty" %}
When responding with `204`, the body **must be empty**.

**Suggestion**

Set the location header to the newly created resource's URI.
{% endtab %}

{% tab title="400: Bad Request Validation of request failed" %}
When request validation fails, `400` Bad Request status code is returned to the client.  \
\
**Requirements**&#x20;

The response messaging should be clear and concise.

**Scenario**&#x20;

`400` may return if the JSON, form submission data, query parameters, or file upload, is invalid or missing in the request body. Query parameters are uncommon for `PUT` requests.
{% endtab %}

{% tab title="401: Unauthorized User is not authenticated" %}
This status code is returned to the client when the user is unauthenticated or the token has expired.
{% endtab %}

{% tab title="403: Forbidden User does not have permission" %}
This status code is returned to the client when the user does not have permission to access the requested resource according to their ACL Role / Group.

**No data** should be returned if the user does not have permission.
{% endtab %}

{% tab title="404: Not Found Requested resource was not found" %}
The `404 Not Found` response code should be returned when the requested resource was not found.

**Requirements**

1\. Any invalid URI with a non-existing resource identified by the URI will return a `404`, unless the implementation allows creating an object using `PUT`.

2\. If an internal dependency related to the resource being requested cannot be resolved, respond with `500`.

**Scenarios**

1\. `PUT /courses/1/frameworks`

If course 1 doesn't exist we should return 404 since the course is the path. This is a hierarchical dependency in the URI.

2\. `PUT /courses/1/frameworks/update`

PUT to the framework collection directly.&#x20;

**Requirement**:

Use HTTP Verbs with RESTful resource paths.

***Avoid using verbs in the URI.***
{% endtab %}

{% tab title="409: Conflict Conflict in state while processing request" %}
The `409 Conflict` status code is returned when there is a conflict while saving an object, which might prevent the application from processing the request.

**Scenarios:**

1\. A user already exists with the same email address or number.

2\. When a unique property is being saved, and the new value is a duplicate of the existing value

3\. Anything that will violate data integrity e.g.  a foreign key violation

4\. A violation of the state of dependent relationships to the object being saved.

5\. Uploading a file older than the existing one.
{% endtab %}

{% tab title="500: Internal Server Error Internal error not caused by user" %}
The client's request was valid, but the application had an issue. The user has no control over resolving the error.

**Requirements**:

1\. Error message should contain:

&#x20;   • Context of the issue

2\. Error message should not contain:

&#x20;   • Leaked Data

&#x20;   • Stack Trace

&#x20;   • Responding with an SQL query that failed

3\. Don't use `500` as a catch-all exception for other types of errors:

&#x20;   • Utilize `404` for not found resources

&#x20;   • Or other applicable `4xx` response codes for client errors

4\. When responding with `500`, the error should be considered a bug. Therefore, it should be investigated and resolved so the client does not experience this again.&#x20;

5\. If an internal dependency related to the resource being requested cannot be resolved, respond with `500`.

**Logging**

Log detailed information on the server to allow technical personnel to debug and determine the cause of the error.
{% endtab %}
{% endtabs %}

## This section contains the API standards and guidelines when implementing a PATCH route

<mark style="color:purple;">`PATCH`</mark> `/api/v2`

The available response codes for a PATCH are listed below the header "Responses"\
Expand the response code to see the guidelines and standards. &#x20;

#### Headers

| Name                                            | Type   | Description  |
| ----------------------------------------------- | ------ | ------------ |
| Authorization<mark style="color:red;">\*</mark> | String | Bearer token |

#### Request Body

| Name  | Type   | Description        |
| ----- | ------ | ------------------ |
| \*    | String | Request parameters |
| {...} | String | JSON request body  |

{% tabs %}
{% tab title="200: OK Request has succeeded" %}
The request was successful.
{% endtab %}

{% tab title="202: Accepted Request has been queued for processing" %}
The `202 Accepted` status code means that we will process the request in a:

&#x20; • Queue

&#x20; • Cron job

&#x20; • Schedule

The response body should be empty.

Relevant information should be set in the headers.

**Suggestion**&#x20;

The response body may be empty with the relevant information set in the headers.
{% endtab %}

{% tab title="204: No Content Response body is empty" %}
When responding with `204`, the body **must be empty**.
{% endtab %}

{% tab title="207: Multi-Status Multiple response status codes" %}
The Patch request conducted multiple requests that required multiple response codes, like a batch job.

**Example**

`PATCH /frameworks?query=123` could update any frameworks matching the query, and each update may have a different status code (200, 404, 400, etc.)
{% endtab %}

{% tab title="400: Bad Request Validation of request failed" %}
When request validation fails, `400` Bad Request status code is returned to the client.  \
\
**Requirements**&#x20;

The response messaging should be clear and concise.

**Scenario**&#x20;

`400` may return if the JSON, form submission data, query parameters, or file upload, is invalid or missing in the request body. Query parameters are uncommon for `PATCH` requests.
{% endtab %}

{% tab title="401: Unauthorized User is not authenticated" %}
This status code is returned to the client when the user is unauthenticated or the token has expired.
{% endtab %}

{% tab title="403: Forbidden User does not have permission" %}
This status code is returned to the client when the user does not have permission to access the requested resource according to their ACL Role / Group.

**No data** should be returned if the user does not have permission.
{% endtab %}

{% tab title="404: Not Found Requested resource was not found" %}
The `404 Not Found` response code should be returned when the requested resource is not found.

**Requirements**

1\. Any invalid URI with a non-existing resource identified by the URI will return a `404`, unless the implementation allows creating an object using `PATCH`.

2\. If an internal dependency related to the resource has not been found for the retrieval of any resource in the URI, we should return `500` instead.

**Scenarios**

1\. `PATCH /courses/1/frameworks`

If course 1 doesn't exist we should return 404 since the course is the path. This is a hierarchical dependency in the URI.

2\. `PATCH /courses/1/frameworks/update`

`PATCH` to the framework collection directly. <br>

**Requirement**:

Use HTTP Verbs with RESTful resource paths.

***Avoid using verbs in the URI.***
{% endtab %}

{% tab title="409: Conflict Conflict in state while processing request" %}
The `409 Conflict` status code is returned when there is a conflict while saving an object, which might prevent the application from processing the request.

**Scenarios**

1\. Anything that will violate data integrity e.g. a foreign key violation.

2\. Deleting the object violates a business relationship. This does not have to be a foreign key violation in the database. Soft deletes will not trigger a foreign key violation but they might cause a business relationship violation.

3\. Deleting a lottery with stages still active.

4\. Framework deleted when already associated with a tree.

Use graphQL for complicated batch jobs or complex queries.
{% endtab %}

{% tab title="500: Internal Server Error Internal error not caused by user" %}
The client's request was valid, but the application had an issue. The user has no control over resolving the error.

**Requirements**

1\. Error message should contain:

&#x20;   • Context of the issue

2\. Error message should not contain:

&#x20;   • Leaked Data

&#x20;   • Stack Trace

&#x20;   • Responding with an SQL query that failed

3\. Don't use `500` as a catch-all exception for other types of errors:

&#x20;   • Utilize `404` for not found resources

&#x20;   • Or other applicable `4xx` response codes for client errors

4\. When responding with `500`, the error should be considered a bug. Therefore, it should be investigated and resolved so the client does not experience this again.

5\. If an internal dependency related to the resource being requested cannot be resolved, respond with `500`.

**Logging**

Log detailed information on the server to allow technical personnel to debug and determine the cause of the error.
{% endtab %}
{% endtabs %}

## This section contains the API standards and guidelines when implementing a DELETE route

<mark style="color:red;">`DELETE`</mark> `/api/v2`

The available response codes for a DELETE are listed below the header "Responses"\
Expand the response code to see the guidelines and standards. &#x20;

#### Query Parameters

| Name | Type   | Description      |
| ---- | ------ | ---------------- |
| \*   | String | Query parameters |

#### Headers

| Name                                            | Type   | Description  |
| ----------------------------------------------- | ------ | ------------ |
| Authorization<mark style="color:red;">\*</mark> | String | Bearer token |

{% tabs %}
{% tab title="200: OK Request has succeeded" %}
The request was successful.
{% endtab %}

{% tab title="202: Accepted Request has been queued for processing" %}
The `202 Accepted` status code means that we will process the request in a:

&#x20; • Queue

&#x20; • Cron job

&#x20; • Schedule

The response body should be empty.

Relevant information should be set in the headers.

**Suggestion**&#x20;

The response body may be empty with the relevant information set in the headers.
{% endtab %}

{% tab title="204: No Content Response body is empty" %}
When responding with `204`, the body **must be empty**.
{% endtab %}

{% tab title="401: Unauthorized User is not authenticated" %}
This status code is returned to the client when the user is unauthenticated or the token has expired.
{% endtab %}

{% tab title="403: Forbidden User does not have permission" %}
This status code is returned to the client when the user does not have permission to access the requested resource according to their ACL Role / Group.

**No data** should be returned if the user does not have permission.
{% endtab %}

{% tab title="404: Not Found Requested resource was not found" %}
The `404 Not Found` response code should be returned when the requested resource is not found.

**Requirements**

1\. Any invalid URI with a non-existing resource identified by the URI will return a `404`.

2\. If an internal dependency related to the resource has not been found for the retrieval of any resource in the URI, we should return `500` instead.

**Scenarios**

1\. `DELETE /courses/1/frameworks`

If course 1 doesn't exist we should return 404 since the course is the path. This is a hierarchical dependency in the URI.

2\. `DELETE /courses/1/frameworks/delete`

`DELETE` to the framework collection directly. <br>

**Requirement**

Use HTTP Verbs with RESTful resource paths.

***Avoid using verbs in the URI.***
{% endtab %}

{% tab title="409: Conflict Conflict in state while processing request" %}
The `409 Conflict` status code is returned when there is a conflict while saving an object, which might prevent the application from processing the request.

**Scenarios:**

1\. Anything that will violate data integrity e.g. a foreign key violation.

2\. Deleting the object violates a business relationship. This does not have to be a foreign key violation in the database. Soft deletes will not trigger a foreign key violation but they might cause a business relationship violation.

3\. Deleting a lottery with stages still active.

4\. If an exam is active when deleting a question.

5\. Framework deleted when already associated with a tree.
{% endtab %}

{% tab title="500: Internal Server Error Internal error not caused by user" %}
The client's request was valid, but the application had an issue. The user has no control over resolving the error.

**Requirements**

1\. Error message should contain:

&#x20;   • Context of the issue

2\. Error message should not contain:

&#x20;   • Leaked Data

&#x20;   • Stack Trace

&#x20;   • Responding with an SQL query that failed

3\. Don't use `500` as a catch-all exception for other types of errors:

&#x20;   • Utilize `404` for not found resources

&#x20;   • Or other applicable `4xx` response codes for client errors

4\. When responding with `500`, the error should be considered a bug. Therefore, it should be investigated and resolved so the client does not experience this again.

5\. If an internal dependency related to the resource being requested cannot be resolved, respond with `500`.

**Logging**

Log detailed information on the server to allow technical personnel to debug and determine the cause of the error.
{% endtab %}

{% tab title="400: Bad Request Validation of request failed" %}
When request validation fails, `400` Bad Request status code is returned to the client.

**Requirements**

The response messaging should be clear and concise.

**Scenario**

`400` may return if the JSON, form submission data, query parameters, or file upload, is invalid or missing in the request body. Query parameters are uncommon for `Delete` requests.
{% endtab %}
{% endtabs %}
