# Custom Pages quickstart

This guide instructs you through replacing the `404` your origin returns with your first page from [Custom Pages](/en/documentation/platform/workloads/#custom-pages).

- Create a custom page set with one page for status code `404`.
- Assign the set in the deployment of your [workload](/en/documentation/platform/workloads/).
- Request a path your origin does not have and get your own page in its place.

Four objects take part, and each one links to the next:

1. The **connector** holds your error page at a path. It already exists. For more information, refer to [Connectors](/en/documentation/platform/connectors/).
2. The **custom page set** binds status code `404` to that path on the connector.
3. The **deployment** of the workload names the set, next to the application it already names.
4. The **request** reaches a path that the application's connector answers with `404`, and the set replaces that answer.

A set changes nothing until a deployment names it. When the application's connector answers `404`, the visitor receives the content of your page in place, with no redirect, and with the status code the page sets. This guide covers Azion Console and the API. The Azion CLI cannot change a deployment that already exists, so it cannot assign a set to your workload.

---

Select the interface you use. The prerequisites and every stage on this page follow that choice.

## Prerequisites

- A workload whose deployment names an application. To create one, refer to [Workloads quickstart](/en/documentation/platform/workloads/quickstart/).
- A path that your application's connector answers with `404`, such as a page that does not exist.
- A connector that serves your error page at a path. To create one, refer to [Connectors](/en/documentation/platform/connectors/).

**Console**

- Access to Azion Console. To sign in, refer to [How to access Azion Console](/en/documentation/guides/platform/account-and-billing/how-to-access-azion-console/).

**API**

- A personal token and `curl`. To create a token, refer to [Personal tokens](/en/documentation/fundamentals/personal-tokens/).
- The ID of the connector that serves your error page.
- The ID of your workload, of its deployment, and of the application the deployment names. If the deployment names a firewall, its ID too.

---

## Create the custom page set

A custom page set is a named list of pages, and it needs at least one. Each page binds one status code to a path on a connector, and it can answer with a status code of its own. The set in this stage keeps the page in cache for `0` seconds and answers with `404`.

**Console**

To create the set in Azion Console:

1. **Open the Custom Pages page**

   Access [Azion Console](https://console.azion.com/) > **Custom Pages**.

2. **Start a new set**

   Select **Create Custom Page**. The **Create Custom Page** page opens.

3. **Name the set**

   In **Name**, enter a name for the set, such as `my-custom-pages`.

4. **Add a page code**

   Select **Create Custom Page Code**.

5. **Select the status code**

   In **Page Code**, select `404`.

6. **Keep the connector page type**

   In **Type**, keep *Page Connector*.

7. **Select your connector**

   In **Connector**, select the connector that serves your error page.

8. **Enter the path of the page**

   In **Page Path (URI)**, enter the path at which the connector serves your page, such as `/html`.

9. **Set the cache time**

   In **Response TTL**, enter `0`.

10. **Set the response status**

    In **Response Custom Status Code**, enter `404`.

11. **Select Create**

The set exists with one page for code `404`. It serves nothing until you assign it to your workload. A set with no page code is refused with the message "You must have at least one custom page code".

**API**

To create the set with the API, send a `POST` request to the custom pages endpoint. Replace `[TOKEN VALUE]` with your personal token and `<connector-id>` with the ID of your connector. Replace `/html` with the path at which the connector serves your page:

```bash
curl --request POST \
  --url https://api.azion.com/v4/workspace/custom_pages \
  --header 'Accept: application/json' \
  --header 'Authorization: Token [TOKEN VALUE]' \
  --header 'Content-Type: application/json' \
  --data '{"name": "my-custom-pages", "active": true, "pages": [
  {"code": "404", "page": {"type": "page_connector", "attributes": {"connector": <connector-id>, "ttl": 0, "uri": "/html", "custom_status_code": 404}}}
]}'
```

The API answers with `201` and the new set, its `id` included. A request with an empty `pages` list is refused with `Ensure this field has at least 1 elements.` Record the `id` of the new set to assign it to your workload. The set exists with one page for code `404`, and it serves nothing until you assign it.

---

## Assign the set to your workload

The deployment of a workload names the application, the firewall, and the custom page set that serve its traffic. A workload holds one deployment, so you assign the set by editing that deployment. The application it already names stays in place.

**Console**

To assign the set in Azion Console:

1. **Open the Workloads page**

   Access [Azion Console](https://console.azion.com/) > **Workloads**.

2. **Open your workload**

   Select your workload. The **Edit Workload** page opens.

3. **Select the set**

   In **Deployment Settings**, select your set in **Custom Page**. Keep **Application** as it is.

4. **Select Save**

Azion Console shows the message "Your workload has been updated". The deployment of the workload names your set.

**API**

To assign the set with the API, send a `PATCH` request to the deployment of your workload. `strategy.attributes` holds the application, the firewall, and the custom page set of the deployment. Send the application the deployment names today, and its firewall if it has one, with the ID of your set in `custom_page`. Replace `<workload-id>`, `<deployment-id>`, `<application-id>`, and `<custom-page-id>`:

```bash
curl --request PATCH \
  --url https://api.azion.com/v4/workspace/workloads/<workload-id>/deployments/<deployment-id> \
  --header 'Accept: application/json' \
  --header 'Authorization: Token [TOKEN VALUE]' \
  --header 'Content-Type: application/json' \
  --data '{
  "strategy": {
    "type": "default",
    "attributes": {
      "application": <application-id>,
      "custom_page": <custom-page-id>
    }
  }
}'
```

The API answers with `202`. The deployment of the workload names your set in `strategy.attributes.custom_page`.

---

## Request a page your origin answers with 404

The check is the same whichever interface assigned the set. In the command, replace `<your-workload-domain>` with the workload domain of your workload, of the form `<id>.map.azionedge.net`. Replace `<missing-path>` with the path your application's connector answers with `404`.

An assigned set does not serve at once. The change to the deployment spreads across Azion's distributed infrastructure, and that takes several minutes, with no guaranteed duration. While it spreads, a request can receive either your origin's `404` or your page. Repeat the request until your page answers. For more information, refer to [Propagation](/en/documentation/platform/workloads/how-it-works/#propagation).

Send a request to the missing path and print the response headers with the body:

```bash
curl -s -D - https://<your-workload-domain>/<missing-path>
```

The response keeps status `404`, from the page's `custom_status_code`. Its body is the document your connector serves at the page's path. When that document is an HTML page, the response reads:

```text
HTTP/2 404 
content-type: text/html; charset=utf-8

<!DOCTYPE html>
<html>
  <head>
  </head>
  <body>
      <h1>Herman Melville - Moby-Dick</h1>
```

The response carries no `Location` header, so the client is not redirected. Your workload answers a missing path with your own page.

---

## Next steps

- [Custom page settings](/en/documentation/platform/workloads/custom-pages/settings.md): Every field of a set and its pages, and the 22 status codes a page can replace.
- [Customize an error page](/en/documentation/guides/application-development/getting-started/customizing-error-response-page.md): Replace the error responses of several status codes at once, each page with its own cache time.
- [Workload settings](/en/documentation/platform/workloads/settings.md#deployment): The deployment fields that name the application, the firewall, and the custom page set.
- [Troubleshoot Workloads](/en/documentation/platform/workloads/troubleshooting.md): Find the cause when a workload answers with an error instead of the response you expect.
