# Relay

_Evervault Relay is a configurable proxy that encrypts or decrypts sensitive data in transit for your APIs and third‑party services._

Relay is a network proxy that encrypts or decrypts sensitive data between a client and a destination server. You can use Relay with your own API or third-party APIs. It's designed to be easy to use and needs minimal changes to your existing code. To process data encrypted by Relay, you can use [Functions](/functions) or [Enclaves](/enclaves).

## Getting started

Relay can be used to encrypt or decrypt data with any API, including third-party APIs. We're going to create a relay that encrypts data before it reaches an API.

> Encrypt and decrypt actions are tied to app keys. This means if you encrypt data with Relay in a [sandbox app](/developers/sandbox), you can't decrypt that data with Relay from a production app (or the other way around). Data can only be encrypted and decrypted using the same Relay, which is tied to the app key.

### Creating a relay

To create a relay, navigate to the Relays tab in the [Evervault Dashboard](https://app.evervault.com), click **Create Relay** and provide the URL for the API you want to use. In this case, we're going to use [PutsReq](https://putsreq.com/) to create a temporary endpoint to act as our API.

![A screenshot of the form inside of the Evervault Dashboard to create a Relay pointed at putsreq.com](/images/relay-putsreq.png)

### Sending a request

When you create a relay, Evervault provisions a domain that you can send requests to. This domain is available in the Relay dashboard, and takes the following form: `[DESTINATION_URL].relay.evervault.app`. Any requests sent to this domain are proxied via Relay before being forwarded to the target endpoint.

### Encrypt data

If you send a request to your relay endpoint, you’ll notice that the request appears in your PutsReq logs, but the value for the `message` is still in plaintext. Next we are going to configure our Relay to encrypt the `message` field before it reaches our API.

Inside of the Evervault Dashboard, click the **Add Route** button to configure a new route. In order to match our request, we need to set the path to the same path as our PutsReq endpoint. Next, we can add a request action to encrypt the `message` field. Select **Add Request Action -> Encrypt -> JSON**, and enter `$.message` as a field to encrypt.

![A screenshot of the form inside of the Evervault Dashboard to create a relay pointed at putsreq.com](/images/relay-putsreq-action.png)

If you send the request again, you should now see that the `message` field has been encrypted in the PutsReq logs.

## Configuration

Relays can be configured to encrypt or decrypt data with route actions. Route actions determine how a relay should handle data on request and response for certain paths and content types. You can configure route actions inside the [Evervault Dashboard](https://app.evervault.com).

- **Encrypting requests**: A common use case for Relay is encrypting sensitive data before it reaches your server. You can do this by configuring a request action to encrypt the fields you want to secure. You can safely store the encrypted data in your database or use it with any other Evervault product.
- **Decrypting requests**: You can also use Relay to share encrypted data with third-party APIs. This allows you to store the encrypted data while still using third-party services as if it were plaintext data. This can be done by creating a relay pointed at the third-party API and configuring a request action to decrypt the fields you want to share.

### Path matching

Route actions will only be applied to requests that match the request path. Paths can be configured to match a specific path or multiple paths with a wildcard.

| Example | Description |
| --- | --- |
| `/` | Matches requests to the root path |
| `/checkout` | Matches requests to /checkout |
| `/patients/*/reports` | Allows for dynamic URL segments such as IDs. Matches requests such as /patients/1/reports, /patients/2/reports, etc. |
| `/**` | Matches all requests |

### Selecting fields

Route actions are only applied to data that matches the list of selected fields defined on an action. Fields can be selected in different ways depending on the type of the request.

#### JSON

For JSON payloads, you can select fields using [JSONPath](https://goessner.net/articles/JsonPath/). JSONPath is a query language for JSON that allows you to select fields by their path in the JSON object.

JSON Payloads are supported for requests where the `content-type` subtype is JSON. The subtype is the part of the content-type header after the /. For example, a content-type of `application/json+charset=utf8` has a subtype of JSON.

| Example | Description |
| --- | --- |
| `$.name` | Matches the 'name' field. |
| `$.address.*` | Matches all fields inside of the 'address' object. |
| `$.patients.*.name` | Select the name field in all patient objects. |
| `$.patients[?(@.country == 'IE')]` | Selects all patient objects where the country field equals IE. |
| `$..*` | Selects all fields inside the JSON object. |

#### Form data

Form data is only supported for requests with a `content-type` of `application/x-www-form-urlencoded` or `multipart/form-data`. Form fields are matched directly by name.

#### Files

Relay supports encrypting and decrypting files in `multipart` and `form-data` requests. Encrypted files will be forwarded on with an unchanged filename, but the bytes in the file will be fully encrypted. There is currently a per-request limit of 25 MB for encryption and decryption.

#### Headers

Headers can be selected by name.

#### XML

To work with XML data, configure your relay for JSON and select the fields to decrypt using standard JSONPath (this approach works for both JSON and XML). To encrypt attributes, you need to use advanced JSONPath selectors.

## Authentication

API key authentication adds an additional layer of security to your relay. When enabled, requests through Relay require a valid Evervault API Key to be passed in a `X-Evervault-Api-Key` header and your App's ID to be passed in a `X-Evervault-App-Id` header.

We strongly recommend enabling API Key Authentication for any Relay configured to decrypt data. However, it may not be necessary when working with your own API which has its own authentication logic. When working with Third-Party API's, it is important to use API Key Authentication to ensure that only your application can access the decrypted data.

You can enable authentication for your relay in the [Evervault Dashboard](https://app.evervault.com) by navigating to the **Authentication settings** page.

> **Authorize access to decrypted data**
>
> Some flows deliver decrypted data directly to a client (e.g.,the [Card Reveal](/cards/reveal) iframe fetching plaintext card data). In these cases, your backend endpoint is the only place where access control is enforced. Evervault has no context for which of your customers can access a given record, so authenticate the request and verify that the caller is authorized before the response is returned.

## Custom domains

By default, Relays are assigned a `relay.evervault.app` domain. You can also configure additional custom domains for your relay. You can add a custom domain to your relay in the Evervault Dashboard by navigating to **Relay -> Settings -> Domains**.

To add a custom domain, you will need to add a CNAME record to your DNS provider that points to `custom-dns.relay.evervault.app`.
Additionally, you will be provided with an ownership validation TXT record that you must put on the `_ev-custom-domain` subdomain of your custom domain.

## mTLS

Relay lets you upload a client certificate to authenticate with the target server over mTLS. You can upload a client cert for your relay in the [Evervault Dashboard](https://app.evervault.com) by navigating to **Relay -> Authentication**. When mTLS is enabled, requests through that relay require an Evervault API Key. This can be added as an HTTP header (`X-Evervault-Api-Key: API-KEY`). If the mTLS cert has a password attached, the cert is encrypted with your team's encryption keys before being sent to Evervault's backend.

## Limitations

The following limitations apply to all requests sent through Relay. If your application requires higher limits, contact [support@evervault.com](mailto:support@evervault.com) to discuss your requirements.

| Description | Limit |
| --- | --- |
| Max payload size | 5mb |
| Max file size | 25mb |
| Max chunked size (transfer-encoding: chunked) | 700kb |
| Connection Timeout | 120s |

## Alerts

Alerts allow you to see errors in Slack or be sent to any webhook URL of your choice. You can create an alert for your relay inside of the Evervault Dashboard by navigating to **Relay -> Alerts -> Add Alert**. When you configure a custom webhook to receive alerts, the following fields will be in the response.

**Payload**

- `relayUuid` — The unique identifier for your relay.
- `teamUuid` — The unique identifier for your team.
- `errorMessage` — Message explaining what went wrong.
- `evMessage` — Message about where the error has occurred.
- `activityLink` — A link to view the failed transaction in the Evervault dashboard.
- `timestamp` — The time the error occurred.
- `errorType` — The relay [error code](#relay-error-codes).
- `statusCode` — The HTTP status code of the response.
- `statusGroup` — 4XX, 5XX, or ERR.
- `inboundDomain` — Your relay domain.

## Error handling

Errors originating from within Relay can be distinguished by the `X-Evervault-Error-Code` header. The responses will have a content type of `application/problem+json` and a payload of the following structure:

```json
{
  "code": "error code used to pinpoint the specific issue in the reference below",
  "title": "human readable title for the error",
  "detail": "longer-form, human readable description of the error",
  "status": 0 // numeric http status code of the response
}
```

**Error Codes**

- `subdomain-not-found` — This error indicates you are sending a request to a relay (e.g., my-api-com.relay.evervault.app) which doesn't exist. Ensure you have entered the Relay subdomain correctly. Also, ensure you have configured your relay correctly by following our Relay documentation.
- `request-timeout` — The target took too long to respond. The error can have many causes ranging from network issues to malformed client requests. Ensure the target domain URL is correct, wait a few moments and try again. If the error persists, reach out to the owner of the target domain through any support channels they have in place.
- `service-unavailable` — The target refused the connection and could not be reached. Ensure the target host is healthy. We recommend that you implement retry behavior to mitigate the impact of brief issues with the network or target host.
- `unsupported-content-type-in-response` — This error occurs when Relay is configured to perform response encryption and receives an unsupported content type as a response from the endpoint. Currently, Relay can only encrypt JSON, XML and multipart/form-data structured data.
- `proxy-auth-failed` — There was an issue authenticating with the provided API key. Ensure that you are using the correct API key.
- `content-length-required` — The Content-Length header is either not present or isn't a number.
- `invalid-request` — This error indicates that an invalid hostname was provided while communicating with Relay in Forward Proxy mode. Ensure you have entered the downstream hostname correctly, and that it can be resolved when requesting it directly.
- `forbidden` — The API key provided does not have sufficient grants to perform the actions requested. Please review the grants given to your API Key.
- `payload-too-large` — This request exceeds the request size limit in Relay. The current per-request limit is 25 MB for encryption/decryption of multipart data, and 5 MB for all other content types.
- `invalid-content-type` — The content type header received by Relay was malformed, preventing the body from being processed.
- `internal-server-error` — There was an issue with Relay itself. Try again in a few moments.
- `decrypt/forbidden` — A ciphertext's data policy prevented it from being decrypted. Ensure your data policy's configuration is correct.
- `no-hostname-in-request` — This error indicates that Relay received a CONNECT request with no hostname while operating in Forward Proxy mode. Ensure you have entered the downstream hostname correctly, and that it can be resolved when requesting it directly.
- `relay-not-found` — There was an issue finding a relay for the provided domain. Make sure you are using the correct domain. If your domain is correct but you are still seeing this issue, ensure you have Relay configured correctly.
- `encrypt/pre-encrypted-data` — There was encrypted data where it wasn't expected. This can mean a number of things: - An inbound request header value contained Evervault encrypted data. - An inbound request payload had Evervault encrypted data as the value of one of the fields, which was not going to be encrypted. - The target URI for the inbound request had Evervault encrypted data as part of the path.
- `proxy-error` — Relay experienced an unexpected networking error while communicating with the downstream service. Please confirm that the downstream service is accessible when not routing through Relay, and ensure that any allowlist requirements have been met.
- `http-connect-not-allowed` — Relay received a request using the CONNECT method which is only supported when interacting in forward proxy mode. Please see advanced usage for further information on using Relay as a forward proxy.
- `bad-request` — The server is unable (or refuses) to process the request sent by the client, due to an issue that is perceived by the server to be a client problem.
- `proxy-authentication-required` — A relay with authentication enabled was requested without valid credentials.

## Forward proxy mode

For most use-cases, the integration described above will be sufficient. However in certain cases, for example when you cannot change the hostname used by a third party library, you may need to integrate Relay as a forward-proxy. Integrating in this manner is more onerous as it requires installing the Relay certificate chain, and configuring the relevant traffic to be proxied via Evervault Relay acting as [an HTTP CONNECT Proxy](https://en.wikipedia.org/wiki/HTTP_tunnel).

To integrate with Relay in forward-proxy mode you will need to:

- Trust the Relay cert chain on your server. The cert can be obtained from [ca.evervault.com](https://ca.evervault.com).
- Identify the best approach for establishing a HTTP Tunnel in your language of choice.
  - For example, in Node.js this is likely using an Agent (which can be created using the [Evervault Node.js SDK](</sdks/nodejs#createrelayhttpsagent()>)), or in JVM based languages this is through the VM's `http.proxyHost` configuration options.
- Supply your proxy authentication credentials to Relay using basic auth. This can be done during either the initial CONNECT request or the subsequent proxied request using the `Proxy-Authorization` header. The value should be basic auth credentials, with your app id as the username, and your api key as the password.
  - Note: Relay will only proxy requests to hosts which have explicitly been created in your app, and cannot be treated as a generic forward proxy.

You can test Relay as a forward proxy using curl:

```sh
curl -x https://relay.evervault.com -U app_id:api_key https://example.com/foo -kv
```

## Using fixed regions

> Using fixed regions isn't generally recommended and Evervault doesn't guarantee reliability or provide an SLA when using a fixed region.

Evervault operates an active-active infrastructure across multiple regions and availability zones. If you need to, you can specify specific regions (either `us` or `eu`) to use with Relay, but this doesn't come with an SLA from Evervault's side. To do this, add `us` or `eu` to your relay URL when making a call. For example, if your base URL is `your-prod-app-12345.relay.evervault.app`, change it to `your-prod-app-12345.us.relay.evervault.app` to send requests to the US region.

- [Functions](/functions): Learn how to use Functions to process encrypted data with your own code.
- [Card Collection](/cards/card-collection): Learn how to use Card Collection to collect cardholder data.

