# Welcome to Alphi

Complex logic made simple with no-code

Alphi is a powerful no-code backend development platform that allows you to create high-performing web applications and microservices without writing code, managing server infrastructure or environments.

Our easy-to-use drag-and-drop interface makes it simple for you to build, extend and integrate data from different sources. Integrations with popular no-code tools like Airtable, Baserow, Memberstack and Outseta make it easier than ever to build secure Web apps on top of your existing stack.

Alphi also includes advanced features like caching, inline expressions, formatting and data transformation to really push the boundaries of no-code.

Sign up now and experience the power of no-code backend development with Alphi.

{% content-ref url="/pages/mqiq35L6ZVKRlQapFI9r" %}
[Projects](/projects/creating-a-project)
{% endcontent-ref %}

{% content-ref url="/pages/pnOPPPNuGvhxCpxHwb7z" %}
[Flow Builder](/flow-builder/overview)
{% endcontent-ref %}

{% content-ref url="/pages/XPaLyvrXHEy9OXlkiadI" %}
[Connections](/connections/overview)
{% endcontent-ref %}

{% content-ref url="/pages/hV13uo03ncZ59pne7cmU" %}
[Authentication](/authentication/overview)
{% endcontent-ref %}

{% content-ref url="/pages/qfFM8RjscGWHgRpGR3ke" %}
[Nodes](/nodes/http-request)
{% endcontent-ref %}


# Creating a project

{% hint style="info" %}
All plans include a 7-day free trial.
{% endhint %}

1. Navigate to [www.alphi.dev](https://www.alphi.dev)
2. Click "Create Project"
3. Select the plan you would like to subscribe to
4. Complete the signup form and click "Sign up"
5. Check your email for the link to login and set your password
6. Complete the onboarding flow to get started

{% hint style="info" %}
If you are an existing user and want to create another project, you can repeat the above steps using the same email address. After logging in, you will be prompted to select the project you would like to open.
{% endhint %}


# Allowed Hosts

Limit access to specific websites

Restrict which websites can call your flows by configuring the allowed hosts.

{% hint style="warning" %}
This is not a security feature, if you would like to secure a flow, please refer to the [auth integrations](/authentication/overview).
{% endhint %}

## URL Format

```
https://www.example.com
```

{% hint style="info" %}
Hosts must not include a trailing slash.
{% endhint %}

## Multiple allowed hosts

To add multiple allowed hosts, separate your URLs using `,` .

```
https://www.example.com, https://example.webflow.io
```


# Collaborators

Collaborate with others

All Alphi subscriptions include at least one additional seat which you can use to invite team members.

{% hint style="warning" %}
Only the **Primary Contact** on an account can invite new team members.&#x20;
{% endhint %}

## Invite a team member

1. Click the 👤 icon within the navigation
2. Select "Team Members"
3. Click "Invite new team member"
4. Enter the name and email address of the person you would like to invite to your Alphi account, then click "Invite new team member".

{% hint style="info" %}
The invitee will receive an email inviting them to set a password and log in.
{% endhint %}


# Overview

Flow builder 101

The flow builder is a visual tool for creating API flows. You can use flows to chain requests, transform data and create production-ready APIs on top of third-party APIs.

{% content-ref url="/pages/NZX0ADbq2xfrF97PZyPm" %}
[Methods](/flow-builder/methods)
{% endcontent-ref %}

{% content-ref url="/pages/B7xHC82sHOo0xSbeKNKX" %}
[Parameters](/flow-builder/parameters)
{% endcontent-ref %}

{% content-ref url="/pages/T5m4R79sUVnyACqxFeaQ" %}
[Nodes](/flow-builder/nodes)
{% endcontent-ref %}

{% content-ref url="/pages/KQhJPBiE47tEbLs5yyF9" %}
[Running](/flow-builder/running)
{% endcontent-ref %}

{% content-ref url="/pages/MRehRCQfDusV0M27XYwh" %}
[Environments](/flow-builder/environments)
{% endcontent-ref %}


# Methods

Flows support both GET and POST methods

## GET

Flows with the method `GET` should only be used to retrieve data. They should not change the state of an external data source, for example, creating, updating or deleting records.

{% hint style="info" %}
GET requests support caching, which can be used to improve the performance of a workflow and reduce the chance of hitting a third-parties API limit.
{% endhint %}

## POST

Flows with the method `POST` can be used to create, read, update and delete external records.


# Parameters

Create dynamic APIs with parameters

## Query Parameters

In a URL, a query parameter is a part of the query string and defined after the question mark (`?`). Query parameters are used to pass additional information.

For example, in the URL `https://www.example.com/search?query=example&page=2` the query parameters are 'query' and 'page', with values 'example' and '2', respectively.

## Body Parameters

Body parameters can be used to send JSON data. Unlike query parameters, it's possible to define the data type of body parameters.

{% hint style="warning" %}
Body parameters are not available for `GET` requests.
{% endhint %}

For example, in a `POST` request which creates a new job listing, the body parameters might include the job's title, location, and salary.


# Nodes

The building blocks

A flow is made up of nodes. Each node serves a specific purpose: connecting to third-party services, transforming data, performing conditional logic and returning responses.

## Name

Each node is given a unique name, e.g. `node_1`, which can be used to reference its data and/or metadata.

To rename a node click the node's name.

{% hint style="warning" %}
Renaming a node does not update the existing references to the node. We recommend that you name a node before creating references to it.
{% endhint %}

## Options

To open the node's configuration options, click the ⚙️ icon.

## Output Data

To view the node's output data, click the ⚙️ icon and expand the output panel.

## Connectors

### Inputs

A node's input connector can be connected to the output of one or more nodes.

{% hint style="info" %}
The start node does not have an input connector.
{% endhint %}

### Outputs

A node's output connector can be connected to one node's input.

{% hint style="info" %}
The logic node has two output connectors.
{% endhint %}


# Running

Executing a flow

There are three different ways to run a flow:

1. Using the **Run** button within the editor
2. Triggering your flow using code, e.g. JavaScript
3. Navigating to the flow URL in your browser (`GET` requests only)

### Run button

The fastest way to run your flow is to use the **Run** button within the editor. This option is perfect for testing.

If the flow does not have any parameters or authentication integrations configured, the flow will be run instantly, and the execution path will be indicated in green.

### Running with parameters

When attempting to run a flow with parameters configured, the run modal will be displayed, allowing you to specify the data included within the request.

### Running with authentication

Similar to running a flow with parameters, if the flow has authentication enabled, the run modal will be displayed, prompting for the user's JWT token.

{% hint style="info" %}
To get a JWT token, please take a look at the [auth integrations](/authentication/overview).
{% endhint %}

## JavaScript

You can use JavaScript to make a [fetch request](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) which will run the flow and return the response.

```javascript
fetch('https://live.api-server.io/run/v1/YOUR_FLOW_ID')
  .then((response) => response.json())
  .then((data) => console.log(data));
```

{% hint style="warning" %}
If your page builder includes the ability to make HTTP requests, you do not need to use JavaScript. For example, WeWeb includes the ability to make HTTP requests.
{% endhint %}

## Browser

To run a flow directly in the browser, copy the flow URL and paste it into the address bar.

{% hint style="info" %}
Only flows with the method `GET` can be run directly in the browser.
{% endhint %}


# Environments

Development and Production

Alphi is a multi-environment nocode backend that allows you two to have two versions of the same endpoint.

## Development

The development flow can **only** be run if the flow is open and in development mode.

{% hint style="info" %}
URL `https://dev.api-server.io/`
{% endhint %}

## Production

The production flow can only be updated if you deploy development to production.

{% hint style="info" %}
URL `https://live.api-server.io/`
{% endhint %}

## Rollback

To revert the changes in development to the last flow deployed to production, select **'Rollback development to production'**.

{% hint style="info" %}
The production flow will not be affected.
{% endhint %}


# Overview

Storing secret keys

{% hint style="info" %}
Connections are secured using AES-256-GCM encryption.
{% endhint %}

When connecting to third-party services such as OpenAI, you must include an API key in the request. This token is used to identify you and track usage so you can be billed accordingly.

{% hint style="danger" %}
Including an API key in client-side JavaScript code is extremely dangerous!
{% endhint %}

Using Alphi connections, you can securely store your API keys in the cloud and reference them within your flow.

It is important to remember that Alphi flows are public by default, so whilst your keys are secure, a malicious user could abuse your quota limits. We recommend integrating an authentication service such as Outseta or Memberstack to secure your flows.

{% content-ref url="/pages/3SN7Ua3RyMgjd6aWRWNm" %}
[Add an API Key](/connections/add-an-api-key)
{% endcontent-ref %}

{% content-ref url="/pages/CG0V0LgBqDKcI6sgq4An" %}
[OAuth Connections](/connections/oauth-connections)
{% endcontent-ref %}


# Add an API Key

Securely store your secret keys

1. In the navigation, click the 🔑 icon
2. Select Add Connection
3. Enter the name of the connection&#x20;
4. Paste your API Key
5. Save the changes

🎉 Congratulations, you successfully added an API Key. The key will now be available within the HTTP Request and Integration nodes.

{% hint style="warning" %}
Once saved, you will not be able to view your API Key again!
{% endhint %}


# OAuth Connections

Grant Alphi access to third-party services

Unlike API keys which have to be copied and pasted, OAuth integration allows you to grant Alphi access to a third-party service such as Airtable and Webflow.

The main benefit of OAuth is the ability to restrict access to specific bases or sites within your account.

Additionally, OAuth connections are easier to manage because, unlike API Keys, they cannot be shared across different services.


# Overview

Securing flows with third-party authentication services

When it comes to building web applications with Alphi you will need an authentication/ membership service to:

* Identify the user executing the flow
* Limit feature access based on the users plan/ subscription
* Allow users to create, read, update and delete records associated with their account

Utilising our authentication integrations, you can connect popular nocode membership services like Outseta and Memberstack in minutes.

## Including a token in a request to Alphi

When running a flow with authentication enabled, you must include the authorisation token in the request.

```
-H "Authorization: Bearer eyJhbGci..."
```

### Javascript Example

```javascript
fetch('https://live.api-server.io/run/v1/YOUR_FLOW_ID', {
    headers: {
      'Authorization': 'Bearer ' + Outseta.getAccessToken()
      // 'Authorization': 'Bearer ' + $memberstackDom.getMemberCookie()
    }
  )
  .then((response) => response.json())
  .then((data) => console.log(data));
```

{% content-ref url="/pages/h7d9OWiHoVZido9eHV1I" %}
[Outseta](/authentication/outseta)
{% endcontent-ref %}

{% content-ref url="/pages/SloSqKCWkPf8dMD8EylZ" %}
[Memberstack](/authentication/memberstack)
{% endcontent-ref %}


# Outseta

All-in-one membership software

## Configuration

{% hint style="info" %}
You can find your Outseta Id in your custom Outseta domain\
For example, if your domain is `https://sandbox.outseta.com`, your Id would be `sandbox`.
{% endhint %}

1. In the navigation, click the ⚙️ icon
2. In the Outseta Id field, enter your Id
3. Save the changes
4. Open the flow you want to secure and add the Outseta node after the `start` node.

🎉 Congratulations, you successfully secured your flow using Outseta.

{% hint style="info" %}
The Outseta node does **not** need to be added after the `start` node if you would like to perform some logic before performing the authorisation check, this is absolutely fine.
{% endhint %}

## Access User Data

To access data associated with the user making the request, you can use the handlebar expressions e.g. `{{request.user.id}}`.

## Properties

<table><thead><tr><th width="188.5">Name</th><th>Expression</th></tr></thead><tbody><tr><td>id</td><td><code>{{request.user.id}}</code></td></tr><tr><td>email</td><td><code>{{request.user.email}}</code></td></tr><tr><td>given_name</td><td><code>{{request.user.given_name}}</code></td></tr><tr><td>account id</td><td><code>{{request.user.outseta:accountUid}}</code></td></tr><tr><td>account client identifier</td><td><code>{{request.user.outseta:accountClientIdentifier}}</code></td></tr><tr><td>is primary</td><td><code>{{request.user.isPrimary}}</code></td></tr><tr><td>subscription id</td><td><code>{{request.user.subscriptionUid}}</code></td></tr><tr><td>plan id</td><td><code>{{request.user.planUid}}</code></td></tr></tbody></table>

## User Token

To access a user token for testing log into your website and run the following code snippet within the console.

```
Outseta.getAccessToken()
```


# Memberstack

Authentication & payments for companies who love Webflow, Stripe, & React.

## Configuration

{% hint style="info" %}
You can find your Memberstack Site Id in your Memberstack V2 dashboard.
{% endhint %}

{% hint style="warning" %}
Memberstack V1 does not display the Site Id within the dashboard instead, you have to extract it from the JWT. Please raise a support ticket if you would like assistance getting your Memberstack V1 Site Id.
{% endhint %}

1. In the navigation, click the ⚙️ icon
2. In the Memberstack Site Id field, enter your Id
3. Save the changes
4. Open the flow you want to secure and add the Memberstack node after the `start` node.

🎉 Congratulations, you successfully secured your flow using Memberstack.

{% hint style="info" %}
The Memberstack node does **not** need to be added after the `start` node. If you would like to perform some logic before performing the authorisation check, this is absolutely fine.
{% endhint %}

### Access User Data

To access data associated with the user making the request, you can use the handlebar expressions e.g. `{{request.user.id}}`.

### Properties

<table><thead><tr><th width="132.5">Name</th><th>Expression</th></tr></thead><tbody><tr><td>id</td><td><code>{{request.user.id}}</code></td></tr><tr><td>email</td><td><code>{{request.user.email}}</code></td></tr></tbody></table>

{% hint style="danger" %}
WARNING the email property was deprecated in Memberstack V2!
{% endhint %}

{% hint style="info" %}
If you would like to access additional user data associated to the logged in user you will need to use the HTTP Request node to call the [Memberstack Admin API](https://support.memberstack.com/hc/en-us/articles/7444702068763-Memberstack-API).
{% endhint %}

## User Token

To access a user token for testing log into your website and run the following code snippet within the console.

#### Memberstack V1

```
MemberStack.getToken()
```

#### Memberstack V2

```
$memberstackDom.getMemberCookie()
```


# Firebase

Coming soon


# HTTP Request

Connect to external APIs

The **HTTP request** node allows you to make external API calls to services not yet listed in our integrations marketplace. For example you could make a request to the OpenAI API or if you would like to send an email via SendGrid you can.

## Options

### Connection

A reference to the connection (API Token) you would like to use within the request.

### URL

The URL for the endpoint to would like to make a request to.

### Method

Each method has a specific purpose, such as requesting data from a server (GET) or submitting data to a server for processing (POST) view the table below for a list of the supported HTTP methods.

<table><thead><tr><th width="172.5">Verb</th><th>Description</th></tr></thead><tbody><tr><td>GET</td><td>Receive data</td></tr><tr><td>POST</td><td>Create new data</td></tr><tr><td>PUT</td><td>Update existing data</td></tr><tr><td>PATCH</td><td>Modify a specific portion of the data</td></tr><tr><td>DELETE</td><td>Delete data</td></tr></tbody></table>

### Headers

A header is a piece of information included in a HTTP request that provides additional context about the content or about the client/server communication. APIs that require headers often specify this in their documentation using the notation "-H".

In most instances you will need to include an authorisation header when connecting to a third-party service. To do this you can reference the connection epecified above.

<table><thead><tr><th width="224.5">Key</th><th>Value</th></tr></thead><tbody><tr><td>Authorization</td><td>Bearer {{connection.key}}</td></tr></tbody></table>

### Query Parameters

A query parameter is a way to pass extra information in a HTTP request, often used to filter or sort the results.

{% hint style="warning" %}
Whilst query parameters are encrypted during transit when using HTTPS it is very poor practice to include sensitive data such as a password in query parameters especially 'GET' requests.
{% endhint %}

### Body Parameters

{% hint style="info" %}
Body parameters are not available for `GET` requests.
{% endhint %}

A body parameter is also a way to pass extra information in a HTTP request, unlike query parameters which are included in the URL, body parameters are sent in the requests body.

{% hint style="info" %}
Unlike query parameters, body parameters support data types allowing you specify the type of the data included in the request. If the data passed is not in the correct format the data will be cast to the correct type or null if an exception occurs.
{% endhint %}

### Cookies

A cookie is also a way to pass extra information in a HTTP request, often used to send authorisation tokens.

### Caching

Caching is a technique used to store frequently accessed data in a temporary storage location, called a cache, so that it can be quickly retrieved without the need to access the original data source. This can significantly improve performance and reduce the load on the original data source.

#### Enable

This option enabled the cache.

#### Duration

This option determines the lend of time the data will be stored in the cache.

#### User Based Caching

{% hint style="info" %}
Requires an active authentication integration
{% endhint %}

In addition to caching based on the query parameters defined, user-based caching ensures the data cached for one logged-in user cannot be returned to another logged-in user.

## Output

### Data

The response returned from the HTTP request.

### Meta Data

#### Status code

This property equals the status code returned from the server.

#### Headers

This property contains the HTTP headers returned from the server.

#### Cookies

This property contains the cookies returned from the server.

## Helpful tips

* We recommend adding the [Logic](/nodes/logic) node after the HTTP request node to check for unexpected errors.


# Logic

If this else that

The **Logic** node is a powerful feature of the flow editor. It can be used to perform complex conditional logic which determines the flow's execution path.

## Options

### Rules

#### Left expression

This represents the value or variable being compared on the left side of the comparison operator. The value can be any data type or expression.

#### Operator

This is the value that is used to perform the comparison between the left and right expressions. The operator can be one of the following:

* equals
* does not equal
* in
* is not in
* greater than
* less than
* greater than or equal to
* less than or equal to

#### Right expression

This represents the value or variable that is being compared on the right side of the comparison operator. The value can be any data type or expression. For some operators like "in" or "is not in", the right expression is expected to be a string or list.

### Group Operator

This is the operator that is used to combine multiple comparison statements. It can be either "AND" or "OR".

<table><thead><tr><th width="161.5">Option</th><th>Description</th></tr></thead><tbody><tr><td>AND</td><td>All the individual comparison statements must be <code>true</code> for the overall comparison to be true.</td></tr><tr><td>OR</td><td>At least one of the individual comparison statements must be <code>true</code> for the overall comparison to be true.</td></tr></tbody></table>

## Output

Returns the current dataset.

## Helpful tips

* Logic nodes can be chained together to perform **If, else if, else if, else** logic.


# Flatten

Simplify multi-dimensional data

The **Flatten** node allows you to convert a nested dataset into a flat table-like structure.

{% hint style="info" %}
The Flatten node does not effect arrays.
{% endhint %}

## Options

### Separator

This option lets you specify the character used as the separator between nested keys.

### Depth

This option allows you to specify the depth of nesting to flatten. A depth of 1 will only flatten the top level of the data, a depth of 2 will flatten the top two levels, and so on.

## Output

Return the flattened dataset.


# Filter Keys

The **Filter Keys** node allows you to filter the keys returned in the dataset.

## Options

### Keys

This option displays a list of keys based on the output of the previous node. Select the keys you would like to return.

## Output

Returns the current dataset with only the selected keys.

## Helpful tips

* Click the **Refresh keys** button to reload the keys.


# Format Keys

Convert to snake case

The **Format Keys** node allows you to convert all the keys at the top level of the dataset to snake\_case.

{% hint style="info" %}
Formatted keys will still include symbols and numbers.
{% endhint %}

## Options

`none`

## Output

Returns the current dataset with the top-level keys converted to snake\_case.


# Rename Keys

The **Rename Keys** node allows you to rename keys in the current dataset.

## Options

### Rules

#### Key

This is the key you would like to rename.

#### Value

This is the new name which will be applied to the property.

## Output

Return the current dataset with the updated keys.

## Helpful tips

* You can use the wildcard prefix to rename part of a key e.g. fields\_\_\*


# Drill Down

The **Dill Down** node allows you to extract a specific subset of a dataset.

## Options

### Key

This option represents the key of the dataset that you would like to drill into.

### Row

This option represents the specific row of the dataset that you would like to extract based on the key you specified.

## Output

Returns the subset as a new dataset.


# Get Values

The **Get Values** node allows you to extract all the values from a specific column of a dataset.

## Options

### Key

This option represents the column that you would like to extract the values from.

## Output

Returns a new dataset with the property **values** which contains an array of the values extracted.


# Set Dataset

The **Set Dataset** node allows you to create a new dataset using JSON, expressions or a combination of the two.

## Options

### Data

This option can be a JSON string or an expression.

## Output

Returns a new dataset based on the data provided.


# Set Property

The **Set Property** node allows you to add/ update a property in the dataset.

## Options

### Key

This option refers to the property you would like to update.

### Value

This is the value which will be applied to the property.

### For each

This option allows you to split an array of values across the rows within the dataset.

## Output

Returns the current dataset with the updated values.


# Set Cookie

The **Set Cookie** node is used to set a cookie on a client's browser, by sending a "Set-Cookie" header in the server's response.

## Options

### Key

This is the name of the cookie.

### Value

This is the value to be stored in the cookie.

### Max age

This is the maximum age of the cookie, in seconds. If not set, the cookie will expire at the end of the session (when the browser is closed).

### Expires

This is the expiration date of the cookie, specified as a date string.

### Path

This is the cookie's path, which defaults to "/".

### Domain

This is the cookie's domain.

### Secure

This indicates that the cookie should only be sent over HTTPS.

### HTTP only

This indicates that the cookie should only be accessible through the HTTP protocol (i.e. JavaScript cannot access it).

### Same site

This attribute controls the cookie's behaviour during cross-site requests to help prevent cross-site scripting (XSS) attacks.

<table><thead><tr><th width="115.5">Option</th><th>Description</th></tr></thead><tbody><tr><td>None</td><td>The cookie will be sent with requests made from the same origin as the current page and some requests from other origins, with limited support among modern browsers, specifically, Chrome supports it and Firefox and Safari default to the 'lax' value if the attribute is not set.</td></tr><tr><td>Lax</td><td>The cookie will be sent with requests made from the same origin as the current page, as well as with "safe" requests made from other origins, providing a balance between security and functionality.</td></tr><tr><td>Strict</td><td>The cookie will only be sent with requests made from the same origin as the current page, providing the highest level of security against cross-site scripting (XSS) attacks.</td></tr></tbody></table>

## Output

Returns the current dataset.


# Set Connection

The **Set Connection** node allows you to update an encrypted connection (API Key).

## Options

### Connection

This is the connection you would like to update.

### Value

This is the value which will be encrypted and stored.

## Output

Returns the current dataset.


# Encode JWT

The **Encode JWT** node is used to create a JSON Web Token (JWT) from a set of user-specified claims and a secret key. JWT is a standard for creating compact and self-contained tokens that can securely transmit information between parties.

## Options

### Type

This is the algorithm that is used to sign the JWT.

### Secret

This is the secret key that is used to sign the JWT.

### Issuer

This is the issuer of the JWT. It is used to specify the entity that issues the JWT.

### Audience

This is the intended audience for the JWT. It can be a string or a list of strings, and it is used to specify the recipients of the JWT.

### Expires

This is the expiration time of the JWT. The encoded JWT will contain an 'exp' claim that holds the expiration time.

### Data

This is a dictionary containing the claims or the data that needs to be encoded in the JWT. It could contain information such as user id, account, subscription, expiration date, etc.

## Output

Returns the encoded JWT.


# Decode JWT

The **Decode JWT** node is used to decode a JSON Web Token (JWT) into its original claims by providing the secret key and a set of options. JWT is a standard for creating compact and self-contained tokens that can securely transmit information between parties.

## Options

### Type

This is the algorithm that is used to verify the JWT. It should match the algorithm that was used to encode the JWT.

### Secret

This is the connection that is used to verify the JWT. It should match the connection that was used to encode the JWT.

### Issuer

This is the expected issuer of the JWT. It should match the issuer that was used to encode the JWT.

### Audience

This is the expected audience of the JWT. It should match the audience that was used to encode the JWT.

## Output

Returns the decoded data from the JWT.

## Helpful tips

* The node will throw a 401 exception if the validation fails.


# Render

The **Render** node allows you to render a template string into a dynamic string using placeholders and HTML attributes.

## Options

### Template

This is the template string containing placeholders for the dynamic data.

{% hint style="info" %}
The most common way to add placeholders in a template string is to use double curly braces `{{data.title}}` although HTML attributes can also be used for HTML templates.&#x20;
{% endhint %}

### Data

This is a dataset containing the data that will be used to populate the template placeholders. It can include variables, lists, dictionaries, etc.

## Output

Returns a new dataset with the property **content,** which includes the dynamic string.

## HTML Attributes

| Attribute     | Description                                                                                                                                                                              |
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ssr-text      | Set the element's textContent property.                                                                                                                                                  |
| ssr-for       | <p>Render a list of items based on an array.</p><p><em>Syntax: item in items where items is the source data array and item is an alias for the array element being iterated on.</em></p> |
| ssr-attr:src  | Set the element's src property.                                                                                                                                                          |
| ssr-attr:href | Set the element's href property.                                                                                                                                                         |

## Helpful tips

* By combining the [HTTP Request](/nodes/http-request) node and the Render node you can create dynamic web pages using page builders like Webflow.


# Ethereum - Verify Message

The **Ethereum - Verify Message** node allows you to verify the authenticity of a message that is claimed to have been signed by a specific Ethereum address. It takes in the Ethereum address, message, and signature as inputs and uses them to verify whether the signature is valid and corresponds to the given Ethereum address and message.

## Options

### Address

This is the Ethereum address that is expected to have signed the message. It should be a valid Ethereum address in hexadecimal format.

### Message

This is the message that needs to be verified. It can be any string value.

### Signature

This is the signature of the message, which is generated using the Ethereum address, private key, and message, and it is used to verify the authenticity of the message and the ownership of the address.

## Output

Returns a new dataset with the property **address.**

{% hint style="danger" %}
If the validation fails, a 401 exception is returned.
{% endhint %}

## Helpful tips

* When testing, you can use [MyEtherWallet](broken://spaces/coEDq3f8yf2o85gBTkJl/pages/cV4OFN5pz9WgkZnTC4qS) to sign messages.


# JSON Response

The **JSON Response** node is used to construct a JSON response which is returned to the client (web browser)

## Options

### Status code

This is the HTTP status code that will be sent with the response. It should be a valid HTTP status code.

### Response

This is the response payload. It can be a JSON object or a string.

{% hint style="info" %}
When returning a string the string will be given the key `detail`.
{% endhint %}

## Output

Returns the response payload.


# HTML Response

The **HTML Response** node is used to construct a HTML response which is returned to the client (web browser).

{% hint style="warning" %}
We recommend enabling SSR mode when using the HTML Response node.
{% endhint %}

## Options

### Status code

This is the HTTP status code that will be sent with the response. It should be a valid HTTP status code.

### Content

This is the content of the response payload. It should be a string containing the HTML content that will be sent in the body of the response.

## Output

Returns the HTML content.

## Helpful tips

* By combining the [Render](/nodes/render) node, you can return dynamic web pages.


# HTTP Redirect

The **HTTP Redirect** node is used to redirect the client (browser) to a new URL.

## Options

### URL

This is the URL to which the client will be redirected.

## Output

Returns a HTML response with the status code 307 (temporary redirect). The response includes a 'Location' header specifying the URL to which the client should be redirected. Once the client receives the redirect response, the client's browser (or other HTTP client) will navigate to the new location specified in the 'Location' header. This is done automatically by the browser without any action required from the user.


# Error

The **Error** node is used to return an error response to the client (browser).

## Options

### Status code

This is the HTTP status code that will be sent with the response. It should be a valid HTTP status code, such as 400 for a bad request or 500 for a server error.

### Message

This is the error message that will be sent in the body of the response. It should be a string containing a brief description of the error.

## Output

Returns the JSON response.

{% hint style="warning" %}
With SSR enabled, the Error node redirects the client (browser) to the error page defined in the start node.
{% endhint %}


