# Applications quickstart

This guide instructs you through serving your origin's content from your first [application](/en/documentation/platform/applications/).

- Create a [connector](/en/documentation/platform/connectors/) that reaches your origin over HTTPS.
- Create an application.
- Add a rule that sends every request to the connector.
- Serve the application from a [workload](/en/documentation/platform/workloads/).
- Send a request to the workload domain and get your origin's answer.

Five parts make the chain, listed in the order this guide uses them:

1. The **connector** holds the address of your origin and the way Azion connects to it.
2. The **application** holds the rules that decide what happens to a request. A new application has no rules.
3. The **rule** on the application pairs a criterion with a behavior. In this guide, the criterion matches every request, and the **Set Connector** behavior names the connector.
4. The **workload** holds the domain that receives requests. Its **deployment** names the application.
5. The **request** to the workload domain meets the rule, and the connector passes it to your origin.

A connector receives requests only once a rule names it, and an application only once a deployment names it.

On an application, you enable three Products: Cache, Application Accelerator, and Image Processor. A new application starts with Cache turned on and the other two turned off, and this guide changes none of them. To turn one on later, open the application's **Main Settings** tab, turn on its switch in **Modules**, and select **Save**. The quickstart of each Product begins where this guide ends, with an application that already serves content.

---

The prerequisites and the five stages show the steps of one interface at a time. Select yours:

## Prerequisites

- An Azion account. For more information, refer to [Create an account](/en/documentation/fundamentals/creating-account/).
- An origin server that answers HTTPS requests on port `443` under a public hostname. This guide writes that hostname as `<your-origin-hostname>`.
- `curl`, to send a request through the workload.

**Console**

You also need access to Azion Console. For more information, refer to [Access Azion Console](/en/documentation/guides/platform/account-and-billing/how-to-access-azion-console/).

**CLI**

You also need the [Azion CLI](/en/documentation/devtools/cli/) on your machine, authorized with a personal token.

**API**

You also need a personal token for the `Authorization` header. To create one, refer to [Manage a personal token](/en/documentation/guides/platform/account-and-billing/personal-tokens/).

---

## Create a connector to your origin

A connector holds the address of your origin and the settings Azion uses to reach it. You create it on its own, outside any application, and a rule names it later. This connector has one address and connects to your origin over HTTPS. It sends your origin's hostname in the `Host` header.

**Console**

To create the connector in Azion Console:

1. **Open the Connectors page**

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

2. **Start a new connector**

3. **Name the connector**

   In **General**, enter `origin-connector` as the **Name**.

4. **Select the HTTP type**

   In **Connector Type**, select the HTTP type.

5. **Enter your origin's hostname as the address**

   Under **Address Management**, enter `<your-origin-hostname>` in **Address**, without a protocol or a port.

6. **Send the same hostname in the Host header**

7. **Connect to the origin over HTTPS only**

   In **Transport Protocol Policy**, select the option that uses HTTPS only.

8. **Select Create**

The connector exists in your account, and the rule you add to the application selects it. For every field of the connector form, refer to [Connectors](/en/documentation/platform/connectors/).

**CLI**

To create the connector with the Azion CLI, put it in a JSON file first. Save this body as `connector.json`, and replace `<your-origin-hostname>` in both places:

```json
{
  "name": "origin-connector",
  "type": "http",
  "attributes": {
    "addresses": [
      { "address": "<your-origin-hostname>" }
    ],
    "connection_options": {
      "transport_policy": "force_https",
      "host": "<your-origin-hostname>"
    }
  }
}
```

`addresses` lists the origin servers, and `connection_options.host` is the `Host` header the connector sends. `force_https` makes every connection to the origin use HTTPS.

Create the connector from the file:

```bash
azion create connector --file connector.json
```

Record the ID of the new connector from the command output: the rule passes it as `<connector-id>`.

**API**

To create the connector with the API, send a `POST` request to the connectors endpoint. Replace `[TOKEN VALUE]` with your personal token, and `<your-origin-hostname>` with the hostname of your origin:

```bash
curl --request POST \
  --url https://api.azion.com/v4/workspace/connectors \
  --header 'Accept: application/json' \
  --header 'Authorization: Token [TOKEN VALUE]' \
  --header 'Content-Type: application/json' \
  --data '{
  "name": "origin-connector",
  "type": "http",
  "attributes": {
    "addresses": [{ "address": "<your-origin-hostname>" }],
    "connection_options": {
      "transport_policy": "force_https",
      "host": "<your-origin-hostname>"
    }
  }
}'
```

The response returns the connector, with a value for every setting the request left out. This excerpt shows those values:

```json
{
  "state": "pending",
  "data": {
    "id": <connector-id>,
    "name": "origin-connector",
    "last_editor": "user@example.com",
    …
    "active": true,
    …
    "type": "http",
    "attributes": {
      "addresses": [
        {
          "active": true,
          "address": "<your-origin-hostname>",
          "http_port": 80,
          "https_port": 443,
          "modules": null
        }
      ],
      "connection_options": {
        "dns_resolution": "both",
        "transport_policy": "force_https",
        "http_version_policy": "http1_1",
        "host": "<your-origin-hostname>",
        "path_prefix": "",
        "following_redirect": false,
        "real_ip_header": "X-Real-IP",
        "real_port_header": "X-Real-PORT"
      },
      "modules": {
        "load_balancer": { "enabled": false, "config": null },
        "origin_shield": { "enabled": false, "config": null }
      }
    },
    …
  }
}
```

The connector is active, and its address takes HTTPS connections on `https_port` `443`. [Load Balancer](/en/documentation/platform/connectors/#load-balancer) and [Origin Shield](/en/documentation/platform/connectors/#origin-shield) start turned off. Record the `id`: the rule passes it as `<connector-id>`.

---

## Create the application

An application holds the rules that decide what happens to each request. It needs only a name, and every other setting keeps its default. Until a rule names a connector, the application has no origin to send requests to.

**Console**

To create the application in Azion Console:

1. **Open the Applications page**

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

2. **Start a new application**

3. **Name the application**

   In **General**, enter `first-application` as the **Name**.

4. **Select Create**

The application exists, and its **Rules Engine** tab holds no rules yet.

**CLI**

To create the application with the Azion CLI:

```bash
azion create application --name first-application --active true
```

The output carries the application's ID:

```text
Created Application with ID <application-id>
```

The application is active and has no rules. Cache and Functions start turned on, and Application Accelerator and Image Processor start turned off. Record the ID: the rule and the deployment pass it as `<application-id>`.

**API**

To create the application with the API, send a `POST` request to the applications endpoint. Replace `[TOKEN VALUE]` with your personal token:

```bash
curl --request POST \
  --url https://api.azion.com/v4/workspace/applications \
  --header 'Accept: application/json' \
  --header 'Authorization: Token [TOKEN VALUE]' \
  --header 'Content-Type: application/json' \
  --data '{"name": "first-application", "active": true}'
```

In the response, `modules` lists the switches the application starts with:

```json
{
  "state": "pending",
  "data": {
    "id": <application-id>,
    "name": "first-application",
    "last_editor": "user@example.com",
    …
    "modules": {
      "cache": { "enabled": true },
      "functions": { "enabled": true },
      "application_accelerator": { "enabled": false },
      "image_processor": { "enabled": false }
    },
    "active": true,
    "debug": false,
    "product_version": "3.0",
    …
  }
}
```

The application is active and has no rules. In `modules`, `cache` and `functions` start turned on, while `application_accelerator` and `image_processor` start turned off. Record the `id`: the rule and the deployment pass it as `<application-id>`.

---

## Send every request to the connector

A rule in [Rules Engine for Applications](/en/documentation/platform/applications/rules-engine/) pairs criteria with behaviors. This rule runs in the request phase. Its criterion, `${uri}` starting with `/`, matches every request. Its behavior, **Set Connector**, sends each matching request to your connector. For more information, refer to [Set Connector](/en/documentation/platform/applications/rules-engine/#set-connector).

The criterion uses `${uri}`, not `${request_uri}`. `${request_uri}` needs Application Accelerator turned on. On an application without it, the API refuses the rule with `400` and error `25047`, `Missing Required Modules`.

**Console**

To create the rule in Azion Console:

1. **Open the application**

   Access [Azion Console](https://console.azion.com/) > **Applications**, and select the application you created.

2. **Select the Rules Engine tab**

3. **Select + Rule**

4. **Name the rule**

   In **General**, enter `send-to-origin` as the **Name**.

5. **Select the request phase**

   In **Phase**, select *Request Phase*. A rule's phase cannot change after you create the rule.

6. **Set the criterion**

   Under **Criteria**, select the variable `${uri}` and the operator `starts_with`, and enter `/` as the argument.

7. **Select the Set Connector behavior**

   Under **Behaviors**, select **Set Connector**.

8. **Select your connector**

   In **Connector**, select the connector you created.

9. **Select Save**

The rule appears in the **Rules Engine** tab, under the **Request** heading.

**CLI**

To create the rule with the Azion CLI, keep the rule in a file: on a command line, the shell would expand `${uri}`. Save this body as `rule.json`, and replace `<connector-id>` with the ID of your connector:

```json
{
  "name": "send-to-origin",
  "active": true,
  "criteria": [
    [
      {
        "variable": "${uri}",
        "conditional": "if",
        "operator": "starts_with",
        "argument": "/"
      }
    ]
  ],
  "behaviors": [
    {
      "type": "set_connector",
      "attributes": { "value": <connector-id> }
    }
  ]
}
```

Each group in `criteria` opens with a condition whose conditional is `if`. Create the rule in the request phase of your application. Replace `<application-id>` with the ID of your application:

```bash
azion create rules-engine --application-id <application-id> --phase request --file rule.json
```

The output carries the rule's ID:

```text
Created Rules Engine with ID <rule-id>
```

The rule is active on your application, and it sends every request to your connector.

**API**

To create the rule with the API, keep the request body in a file: on a command line, the shell would expand `${uri}`. Save this body as `rule.json`, and replace `<connector-id>` with the ID of your connector:

```json
{
  "name": "send-to-origin",
  "active": true,
  "criteria": [
    [
      {
        "variable": "${uri}",
        "conditional": "if",
        "operator": "starts_with",
        "argument": "/"
      }
    ]
  ],
  "behaviors": [
    {
      "type": "set_connector",
      "attributes": { "value": <connector-id> }
    }
  ]
}
```

Each group in `criteria` opens with a condition whose conditional is `if`. Send a `POST` request to the request-phase rules of your application. Replace `<application-id>` with the ID of your application:

```bash
curl --request POST \
  --url https://api.azion.com/v4/workspace/applications/<application-id>/request_rules \
  --header 'Accept: application/json' \
  --header 'Authorization: Token [TOKEN VALUE]' \
  --header 'Content-Type: application/json' \
  --data @rule.json
```

The response carries the stored rule. This excerpt keeps its `id`, its criterion, its behavior, and its `order`:

```json
{
  "state": "pending",
  "data": {
    "id": <rule-id>,
    "name": "send-to-origin",
    "active": true,
    "criteria": [
      [
        {
          "conditional": "if",
          "variable": "${uri}",
          "operator": "starts_with",
          "argument": "/"
        }
      ]
    ],
    "behaviors": [
      {
        "type": "set_connector",
        "attributes": { "value": <connector-id> }
      }
    ],
    "description": "",
    "order": 0,
    …
  }
}
```

`order` is `0`, the position of the first rule on the application. The rule is active, and it sends every request to your connector.

---

## Serve the application from a workload

A workload holds what receives requests: the domain, the protocols, and the certificates. The application holds none of these settings. The workload's deployment names the application it runs, and the current deployment is the one that serves requests. A new workload answers on a workload domain that Azion assigns under `map.azionedge.net`.

**Console**

To create the workload and its deployment in Azion Console:

1. **Open the Workloads page**

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

2. **Start a new workload**

   The **Create Workload** page opens.

3. **Name the workload**

   Enter a name, such as `first-workload`.

4. **Select your application**

   Under **Deployment Settings**, set **Application** to the application you created.

5. **Leave Firewall and Custom Page empty**

6. **Select Create Workload**

The workload exists, and its deployment names your application. To copy the address that the final request goes to, select **Copy Workload URL**.

**CLI**

To create the workload with the Azion CLI:

```bash
azion create workload --name first-workload --active true
```

The output carries the workload's ID:

```text
Created Workload with ID <workload-id>
```

Create the deployment that names your application. Replace `<workload-id>` and `<application-id>`:

```bash
azion create workload-deployment --workload-id <workload-id> \
  --name first-deployment --application-id <application-id> \
  --strategy-type default --active true --current true
```

The output carries the deployment's ID:

```text
Created Workload Deployment with ID <deployment-id>
```

`--current true` makes this deployment the one the workload serves. It names your application and no firewall.

To find the workload domain, describe the workload in JSON:

```bash
azion describe workload --workload-id <workload-id> --format json
```

The `workload_domain` field holds the domain that the final request goes to.

**API**

To create the workload with the API, send a `POST` request to the workloads endpoint. `infrastructure` set to `1` selects the production infrastructure, and `workload_domain_allow_access` set to `true` lets the workload answer on its workload domain:

```bash
curl --request POST \
  --url https://api.azion.com/v4/workspace/workloads \
  --header 'Accept: application/json' \
  --header 'Authorization: Token [TOKEN VALUE]' \
  --header 'Content-Type: application/json' \
  --data '{
  "name": "first-workload",
  "active": true,
  "infrastructure": 1,
  "workload_domain_allow_access": true
}'
```

The response carries the starting settings of the workload and the domain Azion assigned to it:

```json
{
  "state": "pending",
  "data": {
    "id": <workload-id>,
    "name": "first-workload",
    "active": true,
    …
    "infrastructure": 1,
    "tls": {
      "certificate": null,
      "ciphers": 7,
      "minimum_version": "tls_1_3"
    },
    "protocols": {
      "http": {
        "versions": ["http1", "http2", "http3"],
        "http_ports": [80],
        "https_ports": [443],
        "quic_ports": [443]
      }
    },
    …
    "domains": [],
    "workload_domain_allow_access": true,
    "workload_domain": "<your-workload-domain>",
    "product_version": "1.0"
  }
}
```

The workload has no domains of its own, and `workload_domain` holds the one Azion assigned. Record the `id` and the `workload_domain`.

Create the deployment that names your application. Send a `POST` request to the deployments of your workload, and replace `<workload-id>` and `<application-id>`:

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

The response returns the new deployment, with your application in `strategy.attributes`. `current` set to `true` makes it the deployment the workload serves.

---

## Send a request through the workload

This stage needs only `curl`, whichever interface you used to build the chain. In the command, replace `<your-workload-domain>` with the workload domain of the workload you created.

A new workload does not answer at once. Its first deployment can take several minutes to reach traffic, and no duration is guaranteed. Until then, the workload domain answers `404` with a placeholder page. While the deployment spreads, answers to the same request can alternate between that `404` and your origin's response. Repeat the request until the answer comes from your origin.

Send a request to the root path of your workload domain:

```bash
curl -i https://<your-workload-domain>/
```

The response is the one your origin returns for `/`: its status, its headers, and its body. Every other path reaches your origin the same way, because the rule matches every URI that starts with `/`. Your application now sends every request on its workload domain to your origin through the connector.

---

## Next steps

- [Cache quickstart](/en/documentation/platform/applications/cache/quickstart.md): Create a cache setting, apply it to one path with a rule, and read whether a response came from cache.
- [Application Accelerator quickstart](/en/documentation/platform/applications/application-accelerator/quickstart.md): Turn on Application Accelerator and cache a listing that varies by a query string argument.
- [Image Processor quickstart](/en/documentation/platform/applications/image-processor/quickstart.md): Turn on Image Processor, give each transformation its own cache entry, and request your first derived image.
- [Rules Engine for Applications](/en/documentation/platform/applications/rules-engine.md): The phases, variables, operators, and behaviors a rule on an application accepts, Set Connector among them.
- [How Applications works](/en/documentation/platform/applications/how-it-works.md): How a request moves from a workload through the rules of an application to an origin.
- [Applications limits](/en/documentation/platform/applications/limits.md): The bounds on an application and on the Products enabled on it.
