# Introduction

Hoverfly Cloud Documentation. Learn how to use Hoverfly Cloud to create and manage virtual services for API simulation and testing

## What is Hoverfly Cloud?

Hoverfly Cloud is a Software-as-a-Service API simulation solution, designed from the ground up for integration, automation and performance.

Hoverfly Cloud allows developers and test engineers to replace the APIs their applications depend on with flexible light-weight simulations.

This decouples the development and testing process from unreliable, expensive test systems and restrictive API sandboxes.

API simulations can be configured to reproduce unexpected API behaviors such as high latency or random failures. This makes it possible to ensure that applications respond gracefully when the APIs they depend on misbehave.

Hoverfly Cloud allows you to speed up delivery, reduce costs, and get resilient software to market faster.

## API Simulation vs Service Virtualization

The technique of simulating (or "virtualizing") application dependencies during development and testing is often referred to as Service Virtualization.

Service Virtualization solutions usually provide tools for virtualizing HTTP/HTTPS services, database connections, various messaging protocols, and even mainframes.

API simulation refers to the virtualization of HTTP/HTTPS APIs only. API Simulation is therefore a type of Service Virtualization.

## Try it out

If you are ready to dive straight in, please visit the [Tutorials ](/tutorials/quickstart)section and complete the Quick start which will get you your first Hoverfly API simulation running in under a minute.


# Use cases for API Simulation

Understand how and where Hoverfly Cloud will add value to your development and testing scenarios.

## Accelerate Front-End Development

* Parallel Development
  * Enable Front-End and Back-End Teams to Work Simultaneously: Remove dependencies between teams by allowing front-end developers to start building and testing their interfaces without waiting for back-end teams to finish API development or infrastructure setup. This promotes agility and reduces bottlenecks in the development process.\
    \&#xNAN;*Example*: A front-end team working on a flight booking app can simulate APIs for flight search and ticketing while the back-end team focuses on database schemas and server logic, ensuring both teams make progress in parallel.
* Build Against Mock APIs
  * Test Against Realistic API Behavior Without Finalized Back-End Code: Mock APIs created with Hoverfly Cloud closely replicate the expected behavior of real APIs, including dynamic responses, stateful interactions, and error scenarios. This provides front-end developers with a realistic testing environment to validate application functionality early.\
    \&#xNAN;*Example*: A developer creating a user profile editor can simulate an API endpoint like `/users/{id}` that supports GET, PUT, and DELETE requests. By using a mock API, they can ensure the application correctly fetches, updates, and deletes user data even if the back-end team hasn’t finalized these features.

## Prototyping and Proof of Concepts

* Mock API Creation
  * Quickly create mock APIs to validate ideas and share functional prototypes with stakeholders.\
    \&#xNAN;*Example*: A product manager preparing a demo for a new mobile app feature can generate a mock API in minutes to simulate how the app retrieves data, impressing stakeholders without waiting for a full implementation.
* Front-End Prototyping
  * Prototype front-end applications against simulated APIs, removing the dependency on back-end teams or environments.\
    \&#xNAN;*Example*: A start-up building an MVP for a social media app can simulate APIs for user posts, comments, and likes, enabling a seamless front-end demo even if no back-end code exists.

## API-First Development

* Support API-First Strategies
  * Empower teams to adopt an API-first approach by providing robust API simulations early in the design phase. This allows front-end and back-end teams to collaborate on a shared understanding of API behavior and iterate quickly on API designs.\
    \&#xNAN;*Example*: A team designing a new API for a healthcare app can simulate endpoints during design reviews, enabling stakeholders to provide feedback before the actual implementation begins.

## Load Testing

* Cost and Outage Mitigation
  * Perform load testing on simulated APIs to avoid expensive usage costs or the risk of outages when testing against live systems.\
    \&#xNAN;*Example*: An organization can simulate their payment gateway API to test their application under high transaction volumes without affecting the live payment system or incurring additional fees.
* Targeted Component Testing
  * Focus testing efforts on specific components without relying on other services that might introduce complexity or instability.\
    \&#xNAN;*Example*: A QA team testing the behavior of a checkout workflow can simulate only the APIs related to product pricing and order placement, bypassing unrelated services like shipping calculations.

## Functional Testing

* Precise and Flexible Mocks
  * Create mock APIs tailored to specific test cases, allowing for reliable and comprehensive testing.\
    \&#xNAN;*Example*: A tester verifying how an app handles invalid input can create a mock API that returns specific error codes or responses when certain conditions are met.
* Simulate Real-World Behaviors
  * Implement advanced behaviors like stateful interactions, logical workflows, or webhook simulations to match real-world API behavior.\
    \&#xNAN;*Example*: A developer testing a subscription management app can simulate a webhook that fires whenever a payment succeeds or fails, ensuring the app handles both scenarios correctly.

## Fault Tolerance Testing

* Simulate API Errors: Test the resilience of your application by configuring mock APIs to behave unpredictably or fail in specific ways.
  * Inject fixed or random latency to simulate network issues.
  * Return HTTP response codes like 500 Internal Server Error or 429 Too Many Requests based on a defined probability.
  * Modify responses dynamically, such as replacing sensitive information in the request or altering the payload.\
    \&#xNAN;*Example*: A tester can simulate a 503 Service Unavailable error to ensure the application gracefully retries the request or shows a user-friendly error message.
* Comprehensive Scenario Coverage: Cover edge cases that are hard to replicate in live environments.
  * *Example 1*: A banking app team can simulate a scenario where a transaction API intermittently fails or delays responses to test how the app handles timeouts and retries.
  * *Example 2*: A team testing an inventory management system can simulate a third-party logistics API going offline to ensure the application handles fallback mechanisms correctly.

## Integration Testing with Third-Party APIs

* Simulate Third-Party API Behavior
  * Mock third-party APIs to avoid dependency on external systems during testing. This ensures a stable and controlled testing environment.\
    \&#xNAN;*Example*: A developer working on an app that integrates with a payment provider like Stripe can simulate payment APIs to test success, failure, and edge cases without using real payment credentials.

## Compliance Testing

* Test Against Regulatory Requirements
  * Simulate API responses with specific formats, headers, or encryption to ensure compliance with industry standards such as GDPR, HIPAA, or PCI DSS.

    *Example*: A financial services app can use Hoverfly Cloud to mock APIs that enforce strict data masking for sensitive fields like credit card

## Developer Sandboxes

* Risk-Free Experimentation
  * Provide customers and partners with simulated APIs that allow them to experiment without risks to production systems.\
    \&#xNAN;*Example*: A SaaS company offering an analytics API can give new customers a sandboxed version where they can try sending data and exploring analytics features.
* Faster Onboarding
  * Accelerate integration by offering prebuilt mock APIs for partners to test against, helping them start sooner and realize the value of your APIs quickly.\
    \&#xNAN;*Example*: An IoT platform onboarding a device manufacturer can provide them with a pre-configured mock API to test device connectivity before rolling out actual APIs.
* Version Management
  * Host and manage multiple versions of your API simulations for different customers or use cases.\
    \&#xNAN;*Example*: A software vendor maintaining both v1 and v2 of their API can provide tailored mock environments for customers using different versions.
* Tailored Simulations
  * Offer customized mock APIs to match specific customer requirements.\
    \&#xNAN;*Example*: A CRM provider can simulate APIs preloaded with customer-specific data, such as contact lists or sales records, for a more personalized integration experience.
* Training Developers and Testers
  * Provide a sandbox for training new team members or educating customers about your APIs without exposing live systems.\
    \&#xNAN;*Example*: A SaaS provider can use Hoverfly Cloud to create an interactive workshop where new developers learn API best practices by interacting with simulated versions of their platform's APIs.


# Key concepts

Understand the core concepts of Hoverfly service virtualization. Learn about services and other key elements for effective API simulations.

## Overview

To get started Hoverfly Cloud, you need to understand a few concepts: Services, Scenarios, Simulations and Behaviors.

## Services

Hoverfly Cloud services simulates real HTTP services such as web APIs and SOAP services. You can think of Hoverfly Cloud services as API simulations, over the wire test doubles, or more highly configurable HTTP stubs and mocks.

Hoverfly Cloud uses our Open Source tool, [Hoverfly](https://github.com/SpectoLabs/hoverfly) to simulate a service. Hoverfly Cloud uses Kubernetes to run and manage multiple copies of Hoverfly, and adds a powerful GUI with many additional capabilities.

A service is a physical running instance of Hoverfly, and it is configured with a Simulation file as described below.

## Simulations

If you have used [Hoverfly](https://github.com/SpectoLabs/hoverfly) you will know that it captures the interactions of a HTTP service in a simulation file.

Simulations are JSON files that contains pairs of HTTP requests and their corresponding HTTP responses, also known as request/response pairs.

You can also create simulations in Hoverfly Cloud. If you have an account you can see yours on the Simulations page [here](https://cloud.hoverfly.io/simulation). Hoverfly Cloud also allows you to create simulations from Swagger Specifications.

The simulation file, once created, defines what the API simulation will look like and how it will respond to requests. You load the simulation file into a Hoverfly service in order to have a real running API Simulation.

Simulations can be configured in many ways. They can serve up static responses, or they can use templating using handlebars syntax to create powerful, flexible responses using logic, arithmetic, looping and state.

A simulation file is made up of request/response pairs. Each pair contains request matchers which are rules governing how the simulation will match an incoming request. For example you can configure a matcher to look for a specific path structure, or header, or some JSON in the body. The associated response is what Hoverfly will send back to the caller, once a request has been matched, and includes the response body, status code and headers.

## Behaviors

Behaviors allow you to change a simulation quickly, for instance making your service simulation badly behaved except in a predictable way which is what you need for testing!

Behaviors are intended to create specific conditions to support testing. A wide range of behaviors is supported including HTTP header errors, data errors, latency simulations and more. This is very useful for understanding how your application behaves under stress or in unpredictable production environments. We recently had a case where customers were struggling to reproduce a problem seen in production in their test environment. Using Hoverfly Cloud they quickly replicated the problem using behaviors and fixed the problem.

## A Scenario

You can use a Hoverfly Cloud scenario to model a business scenario, for example modelling a payment gateway where all services are working normally, or conversely a flaky third-party API that intermittently fails. A mobile banking app could then be tested to ensure it could handle all these situations appropriately.

Scenarios can be combined with behaviors. A 'business as normal scenario' can be reconfigured with behaviors to predictably inject a variety of errors, for instance retail application could have a Black Friday scenario where there is adverse network latency.

A scenario can consist of a collection of services. For example, suppose you are testing an application to support mortgage approvals. A scenario would define multiple services such as the Land Registry to validate the property reference, postcode validation, customer validation, credit checks, and so on. This complex data-rich set of services would change each time you change and test your application. You would be forced to manually test your application. Using a Hoverfly scenario you could capture the multiple interactions with services and allow the test to be automated.

A scenario describes multiple services and their configuration data and can be started in seconds.

## The Hoverfly Cloud CLI (hcc)

The Hoverfly Cloud command line tool (hcc) can be used to:

* Create simulations locally by capturing and exporting traffic between a client and an API
* Upload simulations to Hoverfly Cloud
* Start and stop remote Hoverfly Cloud services and scenarios
* Provide a local reverse proxy server for accessing an authenticated Hoverfly Cloud service.

![](/files/-LQiqYqyt6qjHKdDl4bw)

The Hoverfly Cloud CLI requires an API token to authenticate with Hoverfly Cloud. It can be installed on development machines or continuous integration servers.


# What's New

Explore what’s new with the latest Hoverfly releases and features and bug fixes in our changelog and how it impacts your service virtualization.

## CSV Data source support using SQL syntax

A simplified SQL like syntax can be used to [query](/create-simulations/using-data-sources-in-simulations/querying-data-sources) the data in a csv data source and retrieve a map of the results for rendering into your response. This syntax can also be used to [update](/create-simulations/using-data-sources-in-simulations/updating-data-in-data-sources) and [delete](/create-simulations/using-data-sources-in-simulations/deleting-data-from-data-sources) from the data source giving your simulations the ability to behave like real services with a persistent database in the backend. CSV Data source support using SQL syntax is only available on the Enterprise plan.

In addition Hoverfly supports a number of templating methods for simpler read, update and delete functions as well a mechanism to [insert](/create-simulations/using-data-sources-in-simulations/inserting-data-into-a-data-source) data into the data source.

\\

## Simulating webhooks and callbacks

You can configure Hoverfly Cloud simulations' endpoints which make a call out to any HTTP endpoint after a given delay to simulate webhooks or callbacks. Simulating webhooks and callbacks is only available on the Enterprise plan.

The capability to make an HTTP callback to a real API after a configured delay following the activation of a simulation endpoint is a powerful feature of Hoverfly Cloud. This can be useful for simulating asynchronous workflows, delayed responses, or real-time event-driven architectures.

Read about more callbacks [here](#simulating-webhooks-and-callbacks)

\\

## String and Validation functions

Support has been added for a number of functions to join, split, replace or perform substring operations on strings.

Information on String functions can be found [here](/create-simulations/using-templating-in-simulations/string-operations)

In addition a number of validation functions have been added to support validation of various types, compare values, and perform regular expression matching on strings.

Information on Validation functions can be found [here](/create-simulations/using-templating-in-simulations/validation-operations)

\\

## Generate synthetic data in API responses

When setting up testing environments for software applications, it's often necessary to have realistic data to test various functionalities. Using synthetic data can help in creating diverse test cases without the need for real data or the risk of exposing sensitive data.

This can also be useful in early stages of development where the real services are not yet available and the mock API’s need to look and feel like the real thing for testing and demonstration purposes.

Hoverfly Cloud now supports built in functions to generate synthetic data in your simulated API responses.

Over and above the existing ability to generate random strings, time and date offsets, and numbers within ranges, as of Hoverfly 1.6.3, the templating engine now includes support for the Go-Faker library which contains over 200 functions for generating data such as names, places, foods, numbers, words, time-zones, currencies, languages and many more forms of data.

Supported Faker functions can be found [here](/create-simulations/using-templating-in-simulations/faker-functions)

\\

## CSV key-value data in API responses

When developing and testing a new system, a set of test data is usually pre-defined that will allow all execution flows to be tested. In these cases, we would want our API simulations to respond with appropriate meaningful data in a way that mimics a real back-end service with a data store.

We could do this by generating multiple hard-coded responses to cater for every conceivable request, however this does mean your simulation files will grow large and contain much duplication.

As of Hoverfly 1.7.0 we now support CSV data sources to be uploaded with the simulations, and these can be used in the templated responses to provide real data back based on a key and column combination. CSV key-value data in API responses is only available on the Enterprise plan.

Combined with the conditional logic built into the templating engine, Hoverfly Cloud can tailor the responses based on the lookup data in the CSV making the mocks both more intelligent, and realistic.

Read about CSV capabilities [here](/create-simulations/using-data-sources-in-simulations)

\\

## Simulating a persistent back-end

Hoverfly Cloud can now retrieve values previously passed into a service and render them back, creating the ability to mock a persistent back-end. Simulating a persistent back-end is only available on the Enterprise plan.

Each Hoverfly instance maintains an in-memory journal containing the previous 1000 Request-Response pairs made to the service.

Hoverfly contains a feature to allow rendering of previous parts of a pre-recorded Request-Response pair from this journal. An identifier for any part of the Request. For example: Request.QueryParam.id is passed into a {{ journal }} templating function along with a value that should satisfy that statement and has been previously recorded in the journal.

The {{ journal }} templating function then retrieves that Request-Response pair from the journal and then renders back any part of it. This is done by specifying an XPath or JSONPath expression along with whether to execute the query against the Request or the Response.

This feature in effect gives the user the ability to retrieve the state historically stored, and render it, which provides the useful illusion of a persistent back-end.

Read about Journal templating features [here](/work-with-services/configuring-journal-indexing)

\\

## Use variables in your simulations

The scripting engine supports custom functions to store and retrieve values in named variables. This allows for the generation of responses that might require looping a certain amount of times, or storing the values of arithmetic functions for further processing later in the template. Variable can also be used to store the result of a faker function and reuse it throughout the template in order to keep consistency in the output.

Read about the use of Variables [here](/create-simulations/using-templating-in-simulations/variables-and-arrays)

\\

## Perform arithmetic in your simulations

You can perform simple addition, subtraction, multiplication and division between any two numbers using the new functions that have been added to the templating engine. These will return the result, either into the template, or if they are enclosed in another function, then into that function.

Read about the arithmetic functions [here](/create-simulations/using-templating-in-simulations/arithmetic-operations)

\\

## Looping over JSON results

The `{{#each}}` block now supports looping over the results of a JSONPath query that returns an array.

This is useful when the incoming Request body contains a collection of keys through which you need to loop and render an appropriate response.

You can nest mathematical functions within a loop and when used with variables, calculate things like totals for rendering in the response as required.

\\


# Hoverfly Cloud AI (Preview)

Intelligent, AI‑driven API simulation. Use natural language via the Model Context Protocol (MCP) to discover, generate, and manage simulations and services—directly from your AI assistant.

> Note: Hoverfly Cloud AI is in active development. Capabilities are not yet fully fledged and functionality may change as we improve the service.

> Access is currently limited to select organizations. If you are interested in trying this new functionality, please [contact us](https://share.hsforms.com/1cTPL5tUURVCWVcLLjTOKtg50v0l) to share your use case and request access.

## Overview

Hoverfly Cloud AI is an intelligent, AI‑driven way to work with API simulations using natural language. Any MCP‑capable assistant can connect to Hoverfly Cloud as a remote MCP server and translate your plain requests into precise actions.

With Hoverfly Cloud AI you can:

* Ask for new simulations to be generated from your codebase, sample payloads, or API specs
* Create, update, and manage simulations and services without leaving your editor
* Get quick status answers and troubleshoot by asking the assistant what’s going on

Your assistant stays in your environment. It simply calls Hoverfly Cloud’s secure HTTP JSON‑RPC MCP endpoint to perform the work in your account.

## Capabilities

Hoverfly Cloud AI exposes MCP tools that map directly to Hoverfly Cloud APIs, so you can:

* Virtualize APIs and build simulations
  * Create, update, list, and delete simulations
  * Generate simulations from OpenAPI/Postman or example requests/responses
* Operate services (your running API simulations)
  * Start services from simulations; update a running service’s simulation
  * Change modes (simulate, capture, spy, passthrough)
  * Apply behaviors such as latency, faults, headers, compression
* Work naturally with AI agents
  * “Create a simulation for new user registration,” “Add a 500ms delay to login,” “What’s the status of my billing API?”
* Generate from your codebase
  * Point at specs or sample payloads; the assistant scaffolds simulations you can refine
* Stay in your development flow
  * Use VS Code/Copilot, Claude Desktop, Cursor, IntelliJ IDEA, or any MCP‑compatible tool
* Read-only mode for safe exploration
  * Discover and inspect simulations without risk of changes by using the `X-MCP-ReadOnly` header

## Use cases

Below are example scenarios that show how natural‑language control accelerates everyday work.

### Create and deploy simulations to replace real APIs in a project

Quickly set up mocks that mirror the external APIs your app already calls:

* Open an AI chat in the context of your codebase that consumes real APIs
* Ask the assistant to build Hoverfly simulations matching those dependencies
* Have it add project config to switch between real and simulated APIs
* Ask it to deploy simulations and start services
* Switch your app’s configuration to the simulated endpoints and run a demo
* Refine: use CSV‑backed data for realistic results or inject a specific error to test failure paths

This saves hours of manual setup while letting you test data and error scenarios safely.

### Generate simulations from API specifications

Turn OpenAPI (Swagger) or Postman collections into running mocks with a prompt:

* Provide your API spec or Postman collection to the assistant
* Ask the assistant to create and deploy simulations that honour the contract—requests and responses for every endpoint
* Instantly provide a reliable mock so frontend and backend teams can work in parallel

### Smart provisioning for test environments

Provision tailored environments for different phases (unit, integration, UAT) using simple commands:

* Organize templates and test data (e.g., CSVs) with a clear folder structure
* Prompt the assistant to analyze the structure and map templates to data
* Ask it to launch a group of services for a named scenario, e.g., “VIP Customer – successful payment”
* When done, instruct it to tear down the group

This gives every team member clean, repeatable environments in seconds.

### Document your API simulation assets

Keep documentation current without the busywork:

* Ask the assistant to “document all running API simulation assets”
* It produces concise docs covering endpoints, expected responses, failure modes, and data dependencies
* Share the output as living, up‑to‑date reference material for the team

## Set up

Hoverfly Cloud provides a remote MCP server over streamable HTTP at the path `/mcp` (HTTP JSON‑RPC). This feature is exposed only as a remote MCP server over streamable HTTP; stdio/local transports are not supported.

Connect your MCP client to that URL and include your Hoverfly Cloud API token as a Bearer token on every request.

You’ll need:

* Hoverfly Cloud MCP URL (`https://cloud.hoverfly.io/mcp`)
* Your Hoverfly Cloud API token. Create and manage tokens from your account page; if you don’t already have one, you can generate one (or more) and revoke them at any time.

### VS Code with GitHub Copilot

Configure an MCP HTTP server in your workspace so Copilot can call Hoverfly Cloud tools.

1. Create `.vscode/mcp.json` in your workspace:

```jsonc
{
  "servers": {
    "hoverfly-cloud": {
      "type": "http",
      "url": "https://cloud.hoverfly.io/mcp",
      "headers": {
        "Authorization": "Bearer <your-hoverfly-cloud-access-token>"
        // Optional: filter to read-only tools while exploring
        // "X-MCP-ReadOnly": "true"
      }
    }
  }
}
```

2. Restart VS Code (or reload the window) and open Copilot Chat. You should see the server in tool discovery; ask Copilot to “list Hoverfly Cloud tools” or “create a simulation named example1.”

### Cursor

Cursor supports MCP servers. Add Hoverfly Cloud as a remote HTTP MCP server:

1. Open Cursor Settings (top right corner) and navigate to Tools & MCP.
2. Click “Add custom MCP” and paste and modify the following JSON configuration:

```jsonc
{
  "mcpServers": {
    "hoverfly-cloud": {
      "type": "http",
      "url": "https://cloud.hoverfly.io/mcp",
      "headers": {
        "Authorization": "Bearer <your-hoverfly-cloud-access-token>"
        // Optional: filter to read-only tools while exploring
        // "X-MCP-ReadOnly": "true"
      }
    }
  }
}
```

3. Save and confirm that the server is added. You should now be able to discover and call Hoverfly Cloud tools from Cursor.

### IntelliJ IDEA

IntelliJ IDEA (JetBrains AI Assistant) can connect to remote MCP servers using the NPX‑based wrapper described in JetBrains’ documentation. This approach lets you access a remote MCP server over streamable HTTP by proxying it locally.

References:

* [Supported transport mechanisms](https://www.jetbrains.com/help/ai-assistant/mcp.html#supported-transport-mechanisms)
* [Workaround for remote servers (NPX wrapper)](https://www.jetbrains.com/help/ai-assistant/mcp.html#workaround-for-remote-servers)

Steps:

1. Open Settings and navigate to the AI Assistant MCP servers configuration.
2. Add a server named “hoverfly-cloud” using the NPX wrapper to reach the remote HTTP endpoint. A working configuration looks like:

```jsonc
{
  "mcpServers": {
    "hoverfly-cloud": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://cloud.hoverfly.io/mcp",
        "--transport",
        "http-first",
        "--header",
        "Authorization:${MCP_AUTH_HEADER}"
      ],
      "env": {
        "MCP_AUTH_HEADER": "Bearer <your-hoverfly-cloud-access-token>"
      }
    }
  }
}
```

3. Apply and restart the IDE if prompted.
4. Use the assistant panel to discover and call tools (e.g., list simulations, create a service from a simulation).

### Other MCP‑compatible tools

Any MCP client that supports remote MCP servers over streamable HTTP can connect with:

* URL: `https://cloud.hoverfly.io/mcp`
* Headers:
  * `Authorization: Bearer <your-hoverfly-cloud-access-token>`
  * Optional `X-MCP-ReadOnly: true` to discover and call read‑only tools only

If your client supports MCP Resources, Hoverfly Cloud also publishes helpful resources (for example, the Hoverfly Simulation JSON Schema) that your AI can load for validation and better reasoning.

### Troubleshooting

* Unauthorized: Ensure your Authorization header is present and the token is valid. Tokens are required on every call.
* Tools not listed: Your account type or read‑only mode may filter tools. Remove `X-MCP-ReadOnly` to see the full set (if allowed by your account).

***

If you’d like help connecting a specific MCP client, contact [Hoverfly Cloud Support](https://share.hsforms.com/1sff4QoSERymmksrTpQFQew50v0l) with your client name and version and we’ll assist.

## Appendix: MCP tool reference

The Hoverfly Cloud MCP server exposes the following tools. Tool visibility and access may be limited by your account type and by read‑only mode.

### Auth

* auth\_current\_user (read‑only)
  * Returns the authenticated user profile.

### Services (running API simulations)

* list\_services (read‑only)
  * List services you can see; supports paging and sorting.
* get\_service (read‑only)
  * Get details for a service by name.
* create\_service
  * Start a new service from a simulation (inline JSON or by name/owner).
* update\_service\_simulation
  * Replace the simulation on a running service (inline JSON or by name/owner).
* update\_service\_mode
  * Change mode: simulate, capture, spy, or passthrough.
* update\_service\_behaviors
  * Apply behaviours (e.g., latency, fault injection, headers, compression).
* delete\_service
  * Delete a service by name.

### Simulations (saved simulations)

* list\_simulations (read‑only)
  * List simulations; supports paging and sorting.
* get\_simulation (read‑only)
  * Fetch a simulation by name (optionally specify owner).
* create\_simulation
  * Create a simulation: provide `name` and `content` JSON. Optional: `findAndReplaceMatchers`, `dataSources`, `callbacks`.
* update\_simulation
  * Update a simulation: same shape as create; PUT semantics.
* delete\_simulation
  * Delete a simulation by name (optionally specify owner).

Notes

* Authentication: Include `Authorization: Bearer <token>` on every call.
* Read‑only mode: Send `X-MCP-ReadOnly: true` to only discover and call read‑only tools.
* Resources: If your MCP client supports “resources”, Hoverfly Cloud can publish helpful docs like the Hoverfly Simulation JSON Schema to aid validation and prompting.


# Dashboard

Access your Hoverfly Cloud dashboard to manage API simulations, create and deploy virtual services, and monitor testing activity.

## Overview

The [dashboard](https://cloud.hoverfly.io/dashboard) allows you to manage Services and Scenarios, quickly start and stop them.

Services and Scenarios on the dashboard include a Journal which logs all activity. Journal entries can be filtered by HTTP status code (eg. 501) or using text search. Note the search fields work together - status code is ANDed with text search, blank values are ignored.

## Services

Click “+ Add” to add a new service to the dashboard — it will start running automatically

**Status**

Status displays running or paused

**Name**

Click for information about the running service and to view the Journal.

**Mode**

Modes can be selected if the service has been configured with a target URL (see Create Simulations for more information about modes)

**Simulation**

Click the simulation name to view and update the running simulation.

**Actions**

*Show Usage* — shows how to use the service using `curl` or Hoverfly Cloud CLI\
\&#xNAN;*Behavior* — set the behavior of a service\
\&#xNAN;*Journal* — hover over to see a tool-tip with summary statistics, click to view the Journal

In the context menu:\
\&#xNAN;*Start* — start a paused service\
\&#xNAN;*Pause* — pause a running service\
\&#xNAN;*Reset* — clear the simulation data, journal entries and state of the service\
\&#xNAN;*Delete* — delete a service from the dashboard

*Re-import simulation* — overwrite the running simulation with the latest one

*Edit Journal Indexing* — edit the indexes configured for the service

## Scenarios

The Scenarios panel shows running scenarios\
Click the > icon to view the services inside the scenario. The same capabilities described above are available for each service.


# Simulation

Create API simulations in 4 convenient ways with Hoverfly Cloud and manage those simulations created by you or your team in one place.

## Overview

Simulations are JSON files that contains pairs of HTTP requests and their corresponding HTTP responses, also known as request/response pairs.

The simulation file, once created, defines what the API simulation will look like and how it will respond to requests. You load the simulation file into a Hoverfly service in order to have a real running API Simulation.

A simulation file consists of a number of request/response pairs. The request part defines "matchers" that you configure to match the pattern of an incoming HTTP request. For example your matcher might be configured to match on an incoming GET request with a path that matches a particular regular expression that you define. When a matcher makes a match, Hoverfly returns the corresponding response that is paired with that request matcher.

Hoverfly Cloud manages simulations created by you or your team (for Enterprise accounts) in one place.

We currently provides 4 convenient ways of creating a simulation:

* [Capture real service activities](/create-simulations/create-simulations#capture-real-service-activities)
* [Manual design using the Simulation Editor](/create-simulations/create-simulations#manual-design-using-the-simulation-editor)
* [Convert from a Swagger Specification](/create-simulations/create-simulations#convert-from-a-swagger-specification)
* [Upload from an existing Hoverfly simulation file](/create-simulations/create-simulations#upload-from-an-existing-simulation-file)

A simulation is only a configuration file, you use it by [importing it into a virtual service](/work-with-services#start-a-service).

## Key features

Hoverfly simulation supports these commonly used Service Virtualization features:

* Strict or loose HTTP request matching based on URL, method, body and header combinations.
* Build dynamic response using templating using handlebars syntax. Read more [here](/create-simulations/using-templating-in-simulations).
* Simulate different responses to the same request based on the current state of a service (Stateful Simulation).
* Render data from a data-source using a provided key. Read more [here](/create-simulations/using-data-sources-in-simulations).
* Add fixed or lognormal delay to the response.

Hoverfly Cloud also provides an easy-to-use Simulation Editor to let you create/edit simulation data without any knowledge of the [Hoverfly simulation schema](https://hoverfly.readthedocs.io/en/latest/pages/reference/simulationschema.html).

The editor gives you auto-completion and suggestions for things like response status code, header names, request matchers and state keys. You can work with the JSON/XML/HTML body using the embedded code editor which provides syntax highlighting and validation. The code editor also supports auto-completion of templating functions, and automatic conversion of encoded body. Batch processing is possible with the global find-and-replace rules.


# Create simulations

Create and manage API simulations with Hoverfly Cloud, capturing real service activity for robust testing.

## Capture real service activities

Capturing live traffic of a real service is a quick way to create a simulation.

You can do that on Hoverfly Cloud if the service is available on the internet. Otherwise, if the service is behind a firewall and Hoverfly Cloud has no access to it, you will need to use [the Hoverfly Cloud CLI](/hoverfly-cloud-cli).

Let's take a look at how you can capture one of the end points from the [Dog CEO API](https://dog.ceo/dog-api/documentation/random). The base URL for the API is `https://dog.ceo`.

{% tabs %}
{% tab title="Using Hoverfly Cloud" %}
In the Simulations page, click the "Capture" button, and select "Yes" to confirm that the API you are going to capture is accessible from the internet.

Then you will be prompted to enter the base URL of the target API.

<figure><img src="/files/p7cmGfpEJTKeUPJ6ZVKb" alt=""><figcaption></figcaption></figure>

Click "OK", and a capture service will start on the Dashboard.

<figure><img src="/files/BHK86WirwfGbKJfWAqOK" alt=""><figcaption></figcaption></figure>

You should make your requests to the capture service URL instead of the original URL. For example, the original URL for getting a random dog image URL is:

```
https://dog.ceo/api/breeds/image/random
```

What you should call instead in this example is:

```
https://dog-ceo-stuawj8.hoverfly.io/api/breeds/image/random
```

You can inspect the requests and responses that have been captured by clicking on the unsaved simulation link. You will see that an endpoint has created to represent the request and a matching response.

<figure><img src="/files/6hbGNO6T6tyhjCH4589v" alt=""><figcaption></figcaption></figure>

The captured simulation can be edited and exported for future use and sharing. It can also be turned into a simulation so that it plays back the responses based on matching requests it receives.
{% endtab %}

{% tab title="Using CLI" %}
[Download the CLI here.](/hoverfly-cloud-cli)

Run the following command to start a capture service on localhost:

```bash
hcc capture start --target-url https://dog.ceo
```

You should provide the base URL of the service to the destination flag.

Once the capture service is started, any requests you made to `http://localhost:8500` will be forwarded to the real service and the requests/responses will be recorded.

You can stop the capture and upload your simulation to your Hoverfly Cloud account with the following command:

```bash
hcc capture stop --simulation-name NAME --api-token TOKEN
```

An API token can be created from your account page.
{% endtab %}
{% endtabs %}

## Manual design using the Simulation Editor

If your API does not yet exist, you can design it using the Simulation Editor. On the Simulations page, click “Create”.

Click on “Add endpoint” to add your first request/response pair.

Use the editor to design the request you want to match and the corresponding response. For example, a simple request matcher for matching `GET` request to the path `/api/breeds/image/random` should look like this:

<figure><img src="/files/m3vX0tUJXiRpOBSLWtfK" alt=""><figcaption></figcaption></figure>

You can click on the “duplicate” burger menu item to reuse an existing pair.

<figure><img src="/files/tMMREz8VIUYKtAnxBi4E" alt=""><figcaption></figcaption></figure>

Once you are happy about your simulation, you can click “Save” to create it.

{% hint style="info" %}
Changes made in the Simulation Editor are not automatically saved. You should click "Save" if you need to keep your changes before navigating to other pages.
{% endhint %}

## Convert from a Swagger Specification

Click “From Swagger” to create a simulation from a Swagger Specification.

{% hint style="info" %}
The current supported Swagger version is 2.0. Both JSON and YAML formats are supported.
{% endhint %}

Click “Choose file” and select a Swagger file from disk.

Click "Confirm" to finish.

Hoverfly Cloud will create one request matcher for each combination of API path and operation in the specification. For example, the [Swagger Petstore GET store order API ](https://petstore.swagger.io/#/store/getOrderById)will be converted to the following matcher:

![](/files/-LfKN6H-ve0N7BEjdp21)

Only one response per API specification is converted, which is usually the 200 successful response. The conversion will look for any example data to use for the response body, but if none were defined in the Swagger specification, Hoverfly Cloud will render a response body that conforms with the Swagger data schema.

For instance, the [Swagger Petstore GET store order API ](https://petstore.swagger.io/#/store/getOrderById)defines the following response data schema:

```javascript
Order{
    id	        integer($int64)
    petId	    integer($int64)
    quantity    integer($int32)
    shipDate	string($date-time)
    status	    string
                Order Status
                Enum:
                [ placed, approved, delivered ]
    complete	boolean
                default: false
}
```

Which converts to the following response body by Hoverfly Cloud:

```javascript
{
  "id": 0,
  "petId": 0,
  "quantity": 0,
  "shipDate": "2000-01-01T00:00:00Z",
  "status": "placed",
  "complete": false
}
```

You can enhance the simulation converted from Swagger by using response templating.

Add templating functions to the above response and enable templating:

![](/files/-LfKT7Gro2sEX05MgiS-)

You should get back a response generated dynamically when you call the endpoint `/v2/store/order/1`:

```javascript
{
  "id": 1,
  "petId": 156,
  "quantity": 3,
  "shipDate": "2019-05-20T13:35:08Z",
  "status": "placed",
  "complete": false
}
```

## Upload from an existing simulation file

Hoverfly Cloud simulation files are interchangeable with [Hoverfly](https://github.com/SpectoLabs/hoverfly). To upload a simulation file go to the Simulations page, and click "Upload", select a file and click "Confirm".

## Learn more

Follow these tutorials to learn more about creating Simulations: [Creating simulations and services](/tutorials/creating-simulations-and-services)


# Configuring Request Matchers

Request Matches are a key concept in Hoverfly. Hoverfly can look for and match on all parts of the incoming request so that it can then respond correctly. This section deals with their configuration.

In order to select a response to return from the sets of request/response pairs that you configure on an API simulation, Hoverfly evaluates the request matchers to find the one that matches the incoming request.

The request matchers are rules that specify what combination of request method, destination, path, headers, query parameters and body content should evaluate positively so that the corresponding response is returned.

Method request matchers can be set to match on ANY HTTP Verb, or a specified HTTP Verb. Destination, path, headers and query parameter matchers can be exact strings, strings containing globs (wildcards), or regular expression patterns.

All of these matchers can be combined so that your simulation can match on specific combinations of method, destination, path, headers, query parameter and body (payload) content.


# JSON Request Matchers on the Body

JSON is the most common data interchange format used for transporting data in web applications. Hoverfly can match the JSON body in incoming requests in order to respond correctly.

### Strategies for matching JSON in the Request

The Body request matcher is what we will be exploring here, in particular, when the body contains JSON data and you need to match on either the data, or the structure of the JSON.

Whether you are doing EXACT, JSON, JSONPartial, JSONPath or Regular Expression matching, the Matcher value must be typed into the Request Matcher's Body field as below:

<figure><img src="/files/sPrI9WweO9dsssHf3MvT" alt=""><figcaption></figcaption></figure>


# EXACT Matcher

Use the exact matcher in Hoverfly Cloud to precisely match request bodies for API simulation and testing.

Unless you need to match the exact payload as a string, down to the spaces and line breaks – this should not be used.

When you choose EXACT matching, Hoverfly will check that the incoming Request Body matches exactly the string that you have set for the Matcher value. If you get one space or line break wrong it won't match.

This does not work well with JSON.


# JSON Matcher

Hoverfly Cloud's JSON Matcher matches exact JSON content, ignoring object order, while referencing exact JSON content - structure and values.

JSON matching will match exactly the JSON that is entered into the editor. The order of the objects is irrelevant, but the JSON document as a whole should evaluate to exactly what is typed into the editor.

Do not confuse this with the EXACT matcher which looks for exact string content. The JSON matcher looks for exact JSON content and doesn't care about order, only structure and values.

### JSON Matching example:

| **Matcher value**                                             | **Positive match payload**           | **Non match payload**                                         |
| ------------------------------------------------------------- | ------------------------------------ | ------------------------------------------------------------- |
| <p>{</p><p>"name": "John",</p><p>"surname": "Doe"</p><p>}</p> | { "surname": "Doe" , "name": "John"} | <p>{</p><p>"name": "Jane",</p><p>"surname": "Doe"</p><p>}</p> |


# JSON Partial Matcher

Use Hoverfly Cloud's JSON partial matcher to match snippets of JSON within request bodies for API simulation and testing.

JSON Partial matching will match if you provide snippet of JSON that exists within the incoming request payload.

Unlike a JSON matcher which does the full comparison matching of two JSON documents (the JSON in the request body with the JSON you have specified as the matcher value), the JSON Partial matcher evaluates if the matcher value is a subset of the incoming JSON document.

The matcher ignores any absent fields and lets you match only the part of JSON document you care about.

### JSON Partial Matching example:

| **Matcher value**                                                             | **Positive match payload**                                                                                                | **Non match payload**                                          |
| ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- |
| {"surname": "Doe"}                                                            | <p>{</p><p>"name": "John",</p><p>"surname": "Doe"</p><p>}</p>                                                             | <p>{</p><p>"name": "John",</p><p>"surname": "Ross"</p><p>}</p> |
| <p>{</p><p>"name": "John",</p><p>"surname": "Doe",</p><p>"age":30</p><p>}</p> | <p>{</p><p>"people": \[</p><p>{</p><p>"name": "John",</p><p>"surname": "Doe",</p><p>"age": 30</p><p>}</p><p>]</p><p>}</p> | <p>{</p><p>"name": "John",</p><p>"surname": "Doe"</p><p>}</p>  |


# JSONPath Matcher

Use Hoverfly Cloud's JSONPath matcher to test for the existence of JSON elements within request bodies using JSONPath queries.

JSONPath matching is used to test for the existence of JSON based on a JSONPath query. If a query is specified that returns a result (any result) after being run against the request body payload, then it matches.

### JSONPath Matching example:

| **Matcher value** | **Positive payload**                                                                                                      | **Non match payload**                                                                                    |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| $.name            | <p>{</p><p>"name": "John",</p><p>"surname": "Doe"</p><p>}</p>                                                             | <p>{</p><p>"age": 30,</p><p>"surname": "Doe"</p><p>}</p>                                                 |
| $.people\[0].age  | <p>{</p><p>"people": \[</p><p>{</p><p>"name": "John",</p><p>"surname": "Doe",</p><p>"age": 30</p><p>}</p><p>]</p><p>}</p> | <p>{</p><p>"people": \[</p><p>{</p><p>"name": "John",</p><p>"surname": "Doe"</p><p>}</p><p>]</p><p>}</p> |


# Regular Expression Matcher

Use Hoverfly Cloud's regular expression matcher to match JSON structures in request bodies when other matchers are insufficient.

You can also use regular expressions if you need to match a particular JSON structure. This is useful if you have various similar request payloads that you cannot discern using JSON, JSON Partial or JSONPath matchers. For example, if you need to match on the existence of a number of certain keys and you do not know their values.

Be aware that the regular expression engine is written in GO and conventions used by that language must be used. In particular it does not support Lookahead or Lookbehind assertions.

### Regular expression matching example:

In this example the regular expression will match provided there is a transactionId with a value of 1000, a store, a clientUniqueId and Items. If any are missing it will not match.

This would not be possible with JSONPartial as the values of store, clientUniqueId and items are variable and not known and cannot be specified in a JSON snippet. Only transactionId is known.

JSONPath cannot currently be used if configured through the Hoverfly Cloud editor as it would only be able to return the existence of a single JSON key at a position within the document. Hoverfly does support matcher chaining which will allow you to chain a number of matchers together, however the Hoverfly Cloud editor does not yet support this yet, and if you would prefer to use this method over regular expressions you will need to manually edit the Hoverfly Simulation as described [here](https://docs.hoverfly.io/en/latest/pages/reference/hoverfly/request_matchers.html#matcher-chaining).)

It should be noted that the regular expression can only check for JSON keys that are in the order stated in the matching string. It will not match if they are in a different order in the payload. The GO regexp package used in Hoverfly does not support Lookahead or Lookbehind assertions.

| **Matcher value**                                                  | **Positive payload**                                                                                                                                                                                                       | <p><strong>Non match payload</strong></p><p><strong>(missing store)</strong></p>                                                                                                                                          |
| ------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| (?s).\*("transactionId": 1000).\*store.\*clientUniqueId.\*items.\* | <p>{</p><p>"someField": "a",</p><p>"transactionId": 1000,</p><p>"anotherField": "b",</p><p>"store": "c",</p><p>"clientUniqueId": "12345",</p><p>"items": \["item1", "item2", "item3"],</p><p>"extraField": "d"</p><p>}</p> | <p>{</p><p>"someField": "a",</p><p>"transactionId": 1000,</p><p>"anotherField": "b",</p><p>"shop": "c",</p><p>"clientUniqueId": "12345",</p><p>"items": \["item1", "item2", "item3"],</p><p>"extraField": "d"</p><p>}</p> |


# Handling the response when Hoverfly cannot match

Learn how Hoverfly Cloud handles unmatched requests, returning a 502 Bad Gateway with a detailed Hoverfly error in the response body.

You will notice that when Hoverfly cannot match you will get a 502 Bad Gateway along with a detailed Hoverfly Error in the response Body.

<figure><img src="/files/D3N105CUwApim0ncnvWy" alt=""><figcaption></figcaption></figure>

This is good for debugging, but when you are running the simulations in a live environment you might want to replace this with a more graceful response that won't break your consuming system.

One approach to dealing with this is to create a "catch all" request/response pair and have it return an appropriate response code and maybe a JSON error that your front end can deal with, for example a 400 and some JSON in the error format you use. To configure this set the matcher's HTTP Verb to ALL, and do not set any other matchers in that endpoint. Then this will match if none of the other matchers are successful in catching the request, and always return something that you control.


# Building a JSON Response

Use Hoverfly Cloud templating to dynamically build JSON responses based on incoming request data like payload, path, query parameter or headers.

Hoverfly Cloud uses {{handlebars syntax}} to provide template scripting with which you can build out a JSON response. Typically, this would involve relying on some data that arrives as part of the request, either as a JSON payload itself, or as part of the path, query parameter, or header.

Templating can be used to perform validation, logic, arithmetic and to generate synthetic data to be used in constructing the body of your response, amongst many other powerful capabilities.

This brief section will discuss the basics of using Hoverfly's templating to generate a JSON response.

You can read more about the other templating features [here](/create-simulations/using-templating-in-simulations).


# Using a JSON object from the Request

Learn how to use data from incoming JSON requests to dynamically build responses in Hoverfly Cloud using Handlebars templating.

You can retrieve any part of a JSON Request payload using the following syntax in the response body. (Note that there are similar functions for working with XML should you need to, as well as for working with JSON that is generated from XML)

```handlebars
{{ Request.Body 'JSONpath' '<<JSONpath query expression>>' }}
```

### Example: Using a JSON object from the Request

| **Request Body**                                                                                                          | **Templating script**                            | **Resulting Response Body** |
| ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | --------------------------- |
| <p>{</p><p>"person":</p><p>{</p><p>"name": "John",</p><p>"surname": "Doe"</p><p>}</p><p>}</p>                             | {{ Request.Body 'JSONpath' '$.person.name' }}    | John                        |
| <p>{</p><p>"people": \[</p><p>{</p><p>"name": "John",</p><p>"surname": "Doe",</p><p>"age": 30</p><p>}</p><p>]</p><p>}</p> | {{ Request.Body 'JSONpath' '$.people\[0].age' }} | 30                          |


# Looping over a JSON array from the Request

Learn how to use Handlebars templating in Hoverfly Cloud to loop over JSON arrays within requests and dynamically generate responses.

Using the `{{#each <<some array>>}} {{/each}}` block in scripting allows you to loop over any array, including JSON arrays.

This is useful if we need to build a response based on all the items that might have been sent in a JSON array as part of the request payload.

```handlebars
{{#each <<some array>>}}  {{/each}}
```

You use {{#each}} in combination with the keyword this which is a pointer to the current object under the iterator.

### Example: Using #each and this to render back items from a JSON array

Notice in this example we are passing the `Request.Body 'JSONpath' '$.people'` function into the #each block. We enclose it in brackets as opposed to handlebars when doing this as it is being used as a parameter to the #each block which is already enclosed in handlebars.

| **Request Body**                                                                                                                                                                                         | **Templating script**                                                                       | **Resulting Response Body** |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | --------------------------- |
| <p>{</p><p>"people": \[</p><p>{</p><p>"name": "John",</p><p>"surname": "Doe",</p><p>"age": 30</p><p>},</p><p>{</p><p>"name": "Jane",</p><p>"surname": "Lee",</p><p>"age": 29</p><p>}</p><p>]</p><p>}</p> | <p>{{#each (Request.Body 'JSONpath' '$.people' ) }}</p><p>{{this.name}}</p><p>{{/each}}</p> | <p>John</p><p>Jane</p>      |

Further to this we can use additional keywords to return the @index, the @key, and whether or not this is pointing at the last item in the array: @last.

### Example: Generating a JSON response while looping over a JSON request

In this example we want to respond with a JSON array containing only the ages of the people passed in with the request.

We iterate over all the array items in the JSON request body, and populate our response based on the request items. We use `this.age` to look into the person object under the iterator and extract the age. We use the last keyword to check that we are not at the end of the array in order to place a comma between the objects in the JSON array.

| **Request Body**                                                                                                                                                                                         | **Templating script**                                                                                                                                                  | **Resulting Response Body**                                  |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
| <p>{</p><p>"people": \[</p><p>{</p><p>"name": "John",</p><p>"surname": "Doe",</p><p>"age": 30</p><p>},</p><p>{</p><p>"name": "Jane",</p><p>"surname": "Lee",</p><p>"age": 29</p><p>}</p><p>]</p><p>}</p> | <p>{ "ages":</p><p>\[</p><p>{{#each (Request.Body 'JSONpath' '$.people') }}</p><p>{{this.age}}</p><p>{{#unless @last}},{{/unless}}</p><p>{{/each}}</p><p>]</p><p>}</p> | <p>{</p><p>"ages": \[</p><p>30,</p><p>29</p><p>]</p><p>}</p> |


# Simulating Webhooks and Callbacks

Simulate webhooks and callbacks with Hoverfly Cloud to test your application's integration with external services.

You can configure Hoverfly Cloud simulations endpoints to make a call out to any HTTP endpoint after a given delay to simulate webhooks or callbacks.

The capability to make an HTTP callback to a real API after a configured delay following the activation of a simulation endpoint is a powerful feature of Hoverfly Cloud. This can be useful for simulating asynchronous workflows, delayed responses, or real-time event-driven architectures.

Callbacks are configured at the simulation level. They can be configured from simulations in the simulation library. They cannot be changed or configured on a simulation already running on a service. If a change is required it must be done to the master simulation, and then re-imported into the running service.

Up to 5 callbacks can be configured per simulation. Each endpoint (request/response pair) can elect whether or not to execute one of the 5 callbacks as required.

### Example (Stripe payment confirmation):

To illustrate the callback feature, consider an example where we need to simulate the Stripe API, and after a simulated payment is made, we need to simulate the webhook that Stripe executes to notify our test backend system of the payment status.

The request/response pairs we have configured might look like this:

<figure><img src="/files/Sh1UfBCHlBK36fcAOJUT" alt=""><figcaption></figcaption></figure>

After confirming the payment, the real Stripe API typically sends a webhook to a predefined endpoint (e.g. <https://dev.pets-r-us.com/webhooks/stripe>) to notify the application of the payment status.

We can configure a callback within this simulation to do exactly that:

<figure><img src="/files/J58UeUwHjk08CxpGOxNS" alt=""><figcaption></figcaption></figure>

We then associate this callback with the "Confirm a payment intent" endpoint. Then after a call to that endpoint is made, Hoverfly Cloud will make a call 1 second later to <https://dev.pets-r-us.com/webhooks/stripe> with the payload that you specify when configuring the callback.

<figure><img src="/files/B0aujQJOMia2RQhOAjOK" alt=""><figcaption></figcaption></figure>

### Using templating within the callback

Note that you can use handlebars templating to modify the query parameters, the header values and the content of the body if you choose to make the callback dynamic. This allows you to use the full scope of the templating engine as well as to include content from the original request. You can read about templating [here](/create-simulations/using-templating-in-simulations)


# Using templating in simulations

Use templating in Hoverfly Cloud simulations to create dynamic responses based on request data and other variables.

Templating in Hoverfly Cloud provides a powerful way to render just about anything you want into the response. It uses the well known {{ handlebars }} syntax where the handlebars surround functions which allow you to control information flow.

**Important**: In order to enable templating you need to explicitly click the "Enable templating" checkbox when crafting your response.

A simple tutorial that covers some of what's possible with templating can be found [here](/tutorials/response-templating).

As this is a fairly large topic it is broken up into sections:

Please select a section from the menu or continue reading about templating [here](/create-simulations/using-templating-in-simulations/render-back-any-part-of-the-request)


# Render back any part of the Request

The most basic thing you might want to do is render back in the response some part of the original request. This can be easily achieved using any of the following functions:

```handlebars
{{ Request.Scheme }} 
{{ Request.QueryParam.myParam }} 
{{ Request.QueryParam.NameOfParameter.[0] }} 
{{ Request.Path.[0] }} 
{{ Request.Method }} 
{{ Request.Host }} 
{{ Request.Body 'jsonpath' '$.id' }} 
{{ Request.Body 'xpath' '/root/id' }}
{{ Request.Body 'jsonpathfromxml' '$.id[0]' }} 
{{ Request.FormData.email }} 
{{ Request.Header.X-Header-Id }} 
{{ Request.Header.X-Header-Id.[0] }} 
```

Note that where the result is an array, you access it it using zero based indexes. Read more about these [here](https://docs.hoverfly.io/en/latest/pages/keyconcepts/templating/templating.html).

Also note that the jsonpathfromxml function converts any XML body into a JSON body, but every element in the resultant structure will be an array, and so the jsonpath used to query it must take that into account.


# Render synthetic data

Hoverfly supports over Faker functions as well as a number of simple data generation functions.

#### FAKER:

Hoverfly supports over 200 Faker functions. You can see the full list [here](/create-simulations/using-templating-in-simulations/faker-functions)

Hoverfly also supports a number of other simple random data generator functions:

<table data-header-hidden><thead><tr><th width="245"></th><th width="343"></th><th></th></tr></thead><tbody><tr><td>A random string</td><td><code>{{ randomString }}</code></td><td>hGfclKjnmwcCds</td></tr><tr><td>A random string with a specified length</td><td><code>{{ randomStringLength 2 }}</code></td><td>KC</td></tr><tr><td>A random boolean</td><td><code>{{ randomBoolean }}</code></td><td>true</td></tr><tr><td>A random integer</td><td><code>{{ randomInteger }}</code></td><td>42</td></tr><tr><td>A random integer within a range</td><td><code>{{ randomIntegerRange 1 10 }}</code></td><td>7</td></tr><tr><td>A random float</td><td><code>{{ randomFloat }}</code></td><td>42</td></tr><tr><td>A random float within a range</td><td><code>{{ randomFloatRange 1.0 10.0 }}</code></td><td>7.4563213423</td></tr><tr><td>A random email address</td><td><code>{{ randomEmail }}</code></td><td>BenClark@photolist.com</td></tr><tr><td>A random IPv4 address</td><td><code>{{ randomIPv4 }}</code></td><td>224.36.27.8</td></tr><tr><td>A random IPv6 address</td><td><code>{{ randomIPv6 }}</code></td><td>41d7:daa0:6e97:6fce:411e:681:f86f:e557</td></tr><tr><td>A random UUID</td><td><code>{{ randomUuid }}</code></td><td></td></tr></tbody></table>


# Faker functions

The following Faker functions are currently supported:

```handlebars
FileExtension: {{ faker 'FileExtension' }}
FileMimeType: {{ faker 'FileMimeType' }}

Name: {{ faker 'Name' }}
NamePrefix: {{ faker 'NamePrefix' }}
NameSuffix: {{ faker 'NameSuffix' }}
FirstName: {{ faker 'FirstName' }}
LastName: {{ faker 'LastName' }}
Gender: {{ faker 'Gender' }}
SSN: {{ faker 'SSN' }}
Hobby: {{ faker 'Hobby' }}
Email: {{ faker 'Email' }}
Phone: {{ faker 'Phone' }}
PhoneFormatted: {{ faker 'PhoneFormatted' }}

Username: {{ faker 'Username' }}

City: {{ faker 'City' }}
Country: {{ faker 'Country' }}
CountryAbr: {{ faker 'CountryAbr' }}
State: {{ faker 'State' }}
StateAbr: {{ faker 'StateAbr' }}
Street: {{ faker 'Street' }}
StreetName: {{ faker 'StreetName' }}
StreetNumber: {{ faker 'StreetNumber' }}
StreetPrefix: {{ faker 'StreetPrefix' }}
StreetSuffix: {{ faker 'StreetSuffix' }}
Zip: {{ faker 'Zip' }}

Gamertag: {{ faker 'Gamertag' }}

BeerAlcohol: {{ faker 'BeerAlcohol' }}
BeerBlg: {{ faker 'BeerBlg' }}
BeerHop: {{ faker 'BeerHop' }}
BeerIbu: {{ faker 'BeerIbu' }}
BeerMalt: {{ faker 'BeerMalt' }}
BeerName: {{ faker 'BeerName' }}
BeerStyle: {{ faker 'BeerStyle' }}
BeerYeast: {{ faker 'BeerYeast' }}

CarMaker: {{ faker 'CarMaker' }}
CarModel: {{ faker 'CarModel' }}
CarType: {{ faker 'CarType' }}
CarFuelType: {{ faker 'CarFuelType' }}
CarTransmissionType: {{ faker 'CarTransmissionType' }}

Noun: {{ faker 'Noun' }}
NounCommon: {{ faker 'NounCommon' }}
NounConcrete: {{ faker 'NounConcrete' }}
NounAbstract: {{ faker 'NounAbstract' }}
NounCollectivePeople: {{ faker 'NounCollectivePeople' }}
NounCollectiveAnimal: {{ faker 'NounCollectiveAnimal' }}
NounCollectiveThing: {{ faker 'NounCollectiveThing' }}
NounCountable: {{ faker 'NounCountable' }}
NounUncountable: {{ faker 'NounUncountable' }}

Verb: {{ faker 'Verb' }}
VerbAction: {{ faker 'VerbAction' }}
VerbLinking: {{ faker 'VerbLinking' }}
VerbHelping: {{ faker 'VerbHelping' }}

Adverb: {{ faker 'Adverb' }}
AdverbManner: {{ faker 'AdverbManner' }}
AdverbDegree: {{ faker 'AdverbDegree' }}
AdverbPlace: {{ faker 'AdverbPlace' }}
AdverbTimeDefinite: {{ faker 'AdverbTimeDefinite' }}
AdverbTimeIndefinite: {{ faker 'AdverbTimeIndefinite' }}
AdverbFrequencyDefinite: {{ faker 'AdverbFrequencyDefinite' }}
AdverbFrequencyIndefinite: {{ faker 'AdverbFrequencyIndefinite' }}

Preposition: {{ faker 'Preposition' }}
PrepositionSimple: {{ faker 'PrepositionSimple' }}
PrepositionDouble: {{ faker 'PrepositionDouble' }}
PrepositionCompound: {{ faker 'PrepositionCompound' }}

Adjective: {{ faker 'Adjective' }}
AdjectiveDescriptive: {{ faker 'AdjectiveDescriptive' }}
AdjectiveQuantitative: {{ faker 'AdjectiveQuantitative' }}
AdjectiveProper: {{ faker 'AdjectiveProper' }}
AdjectiveDemonstrative: {{ faker 'AdjectiveDemonstrative' }}
AdjectivePossessive: {{ faker 'AdjectivePossessive' }}
AdjectiveInterrogative: {{ faker 'AdjectiveInterrogative' }}
AdjectiveIndefinite: {{ faker 'AdjectiveIndefinite' }}

Pronoun: {{ faker 'Pronoun' }}
PronounPersonal: {{ faker 'PronounPersonal' }}
PronounObject: {{ faker 'PronounObject' }}
PronounPossessive: {{ faker 'PronounPossessive' }}
PronounReflective: {{ faker 'PronounReflective' }}
PronounDemonstrative: {{ faker 'PronounDemonstrative' }}
PronounInterrogative: {{ faker 'PronounInterrogative' }}
PronounRelative: {{ faker 'PronounRelative' }}

Connective: {{ faker 'Connective' }}
ConnectiveTime: {{ faker 'ConnectiveTime' }}
ConnectiveComplaint: {{ faker 'ConnectiveComplaint' }}
ConnectiveListing: {{ faker 'ConnectiveListing' }}
ConnectiveCasual: {{ faker 'ConnectiveCasual' }}
ConnectiveExamplify: {{ faker 'ConnectiveExamplify' }}

Word: {{ faker 'Word' }}
LoremIpsumWord: {{ faker 'LoremIpsumWord' }}
Question: {{ faker 'Question' }}
Phrase: {{ faker 'Phrase' }}

Fruit: {{ faker 'Fruit' }}
Vegetable: {{ faker 'Vegetable' }}
Breakfast: {{ faker 'Breakfast' }}
Lunch: {{ faker 'Lunch' }}
Dinner: {{ faker 'Dinner' }}
Snack: {{ faker 'Snack' }}
Dessert: {{ faker 'Dessert' }}

UUID: {{ faker 'UUID' }}
FlipACoin: {{ faker 'FlipACoin' }}

Color: {{ faker 'Color' }}
HexColor: {{ faker 'HexColor' }}
SafeColor: {{ faker 'SafeColor' }}

URL: {{ faker 'URL' }}
DomainName: {{ faker 'DomainName' }}
DomainSuffix: {{ faker 'DomainSuffix' }}
IPv4Address: {{ faker 'IPv4Address' }}
IPv6Address: {{ faker 'IPv6Address' }}
MacAddress: {{ faker 'MacAddress' }}
HTTPMethod: {{ faker 'HTTPMethod' }}
HTTPVersion: {{ faker 'HTTPVersion' }}
UserAgent: {{ faker 'UserAgent' }}
ChromeUserAgent: {{ faker 'ChromeUserAgent' }}
FirefoxUserAgent: {{ faker 'FirefoxUserAgent' }}
OperaUserAgent: {{ faker 'OperaUserAgent' }}
SafariUserAgent: {{ faker 'SafariUserAgent' }}

MonthString: {{ faker 'MonthString' }}
WeekDay: {{ faker 'WeekDay' }}
TimeZone: {{ faker 'TimeZone' }}
TimeZoneAbv: {{ faker 'TimeZoneAbv' }}
TimeZoneFull: {{ faker 'TimeZoneFull' }}
TimeZoneRegion: {{ faker 'TimeZoneRegion' }}

CreditCardCvv: {{ faker 'CreditCardCvv' }}
CreditCardExp: {{ faker 'CreditCardExp' }}
CreditCardType: {{ faker 'CreditCardType' }}
CurrencyLong: {{ faker 'CurrencyLong' }}
CurrencyShort: {{ faker 'CurrencyShort' }}
AchRouting: {{ faker 'AchRouting' }}
AchAccount: {{ faker 'AchAccount' }}
BitcoinAddress: {{ faker 'BitcoinAddress' }}
BitcoinPrivateKey: {{ faker 'BitcoinPrivateKey' }}

BS: {{ faker 'BS' }}
BuzzWord: {{ faker 'BuzzWord' }}
Company: {{ faker 'Company' }}
CompanySuffix: {{ faker 'CompanySuffix' }}
Job: {{ faker 'Job' }}
JobDescriptor: {{ faker 'JobDescriptor' }}
JobLevel: {{ faker 'JobLevel' }}
JobTitle: {{ faker 'JobTitle' }}

HackerAbbreviation: {{ faker 'HackerAbbreviation' }}
HackerAdjective: {{ faker 'HackerAdjective' }}
HackerNoun: {{ faker 'HackerNoun' }}
HackerPhrase: {{ faker 'HackerPhrase' }}
HackerVerb: {{ faker 'HackerVerb' }}

HipsterWord: {{ faker 'HipsterWord' }}

AppName: {{ faker 'AppName' }}
AppVersion: {{ faker 'AppVersion' }}
AppAuthor: {{ faker 'AppAuthor' }}

PetName: {{ faker 'PetName' }}
Animal: {{ faker 'Animal' }}
AnimalType: {{ faker 'AnimalType' }}
FarmAnimal: {{ faker 'FarmAnimal' }}
Cat: {{ faker 'Cat' }}
Dog: {{ faker 'Dog' }}

Emoji: {{ faker 'Emoji' }}
EmojiDescription: {{ faker 'EmojiDescription' }}
EmojiAlias: {{ faker 'EmojiAlias' }}
EmojiTag: {{ faker 'EmojiTag' }}

Language: {{ faker 'Language' }}
LanguageAbbreviation: {{ faker 'LanguageAbbreviation' }}
ProgrammingLanguage: {{ faker 'ProgrammingLanguage' }}
ProgrammingLanguageBest: {{ faker 'ProgrammingLanguageBest' }}

Digit: {{ faker 'Digit' }}
Letter: {{ faker 'Letter' }}

CelebrityActor: {{ faker 'CelebrityActor' }}
CelebrityBusiness: {{ faker 'CelebrityBusiness' }}
CelebritySport: {{ faker 'CelebritySport' }}

MinecraftOre: {{ faker 'MinecraftOre' }}
MinecraftWood: {{ faker 'MinecraftWood' }}
MinecraftArmorTier: {{ faker 'MinecraftArmorTier' }}
MinecraftArmorPart: {{ faker 'MinecraftArmorPart' }}
MinecraftWeapon: {{ faker 'MinecraftWeapon' }}
MinecraftTool: {{ faker 'MinecraftTool' }}
MinecraftDye: {{ faker 'MinecraftDye' }}
MinecraftFood: {{ faker 'MinecraftFood' }}
MinecraftAnimal: {{ faker 'MinecraftAnimal' }}
MinecraftVillagerJob: {{ faker 'MinecraftVillagerJob' }}
MinecraftVillagerStation: {{ faker 'MinecraftVillagerStation' }}
MinecraftVillagerLevel: {{ faker 'MinecraftVillagerLevel' }}
MinecraftMobPassive: {{ faker 'MinecraftMobPassive' }}
MinecraftMobNeutral: {{ faker 'MinecraftMobNeutral' }}
MinecraftMobHostile: {{ faker 'MinecraftMobHostile' }}
MinecraftMobBoss: {{ faker 'MinecraftMobBoss' }}
MinecraftBiome: {{ faker 'MinecraftBiome' }}
MinecraftWeather: {{ faker 'MinecraftWeather' }}

```


# Render dates and times with offsets

Hoverfly Cloud has powerful templating features to render the date and time with offsets as required based on the underlying Go programming language.

The Go language uses a fixed reference time — **Mon Jan 2 15:04:05 MST 2006** — to define date/time layouts. Each element of that date maps to a component (e.g., `2006` = year, `01` = month, `02` = day, `15` = 24h hour, `03` = 12h hour, `04` = minutes, `05` = seconds, `MST` = time zone). This format, inherited from Plan 9, was chosen as a mnemonic since the digits **1–7** appear in order across the reference. <https://golang.org/pkg/time/#Parse>

NOTE! It is important to use the fixed referenced date and time when applying a format to a date. Do not use todays date or any other date.

<table data-header-hidden><thead><tr><th></th><th width="285"></th><th></th></tr></thead><tbody><tr><td>Description</td><td>Example</td><td>Result</td></tr><tr><td><p>The current date time with offset, in the given format.</p><p>For example:</p><ul><li>The current date time plus 1 day in unix timestamp</li><li>The current date time in ISO 8601 format</li><li>The current date time minus 1 day in custom format</li></ul></td><td><ul><li><code>{{ now '1d' 'unix' }}</code></li><li><code>{{ now '' '' }}</code></li><li><code>{{ now '-1d' '2006-Jan-02' }}</code></li></ul></td><td><ul><li>1136300645</li><li>2006-01-02T15:04:05Z</li><li>2006-Jan-01</li></ul></td></tr></tbody></table>

## Examples

<table><thead><tr><th width="135">Format</th><th width="321">Handlebars syntax</th><th>Result</th></tr></thead><tbody><tr><td>ANSIC</td><td><code>{{now '' 'Mon Jan _2 15:04:05 2006'}}</code></td><td>Wed Sep 17 14:31:18 2025</td></tr><tr><td>UnixDate</td><td><code>{{now '' 'Mon Jan _2 15:04:05 MST 2006'}}</code></td><td>Wed Sep 17 14:31:18 UTC 2025</td></tr><tr><td>RubyDate</td><td><code>{{now '' 'Mon Jan 02 15:04:05 -0700 2006'}}</code></td><td>Wed Sep 17 14:31:18 +0000 2025</td></tr><tr><td>RFC822</td><td><code>{{now '' '02 Jan 06 15:04 MST'}}</code></td><td>17 Sep 25 14:31 UTC</td></tr><tr><td>RFC822Z</td><td><code>{{now '' '02 Jan 06 15:04 -0700'}}</code></td><td>17 Sep 25 14:31 +0000</td></tr><tr><td>RFC850</td><td><code>{{now '' 'Monday, 02-Jan-06 15:04:05 MST'}}</code></td><td>Wednesday, 17-Sep-25 14:31:18 UTC</td></tr><tr><td>RFC1123</td><td><code>{{now '' 'Mon, 02 Jan 2006 15:04:05 MST'}}</code></td><td>Wed, 17 Sep 2025 14:31:18 UTC</td></tr><tr><td>RFC1123Z</td><td><code>{{now '' 'Mon, 02 Jan 2006 15:04:05 -0700'}}</code></td><td>Wed, 17 Sep 2025 14:31:18 +0000</td></tr><tr><td>RFC3339</td><td><code>{{now '' '2006-01-02T15:04:05Z07:00'}}</code></td><td>2025-09-17T14:31:18Z</td></tr><tr><td>RFC3339Nano</td><td><code>{{now '' '2006-01-02T15:04:05.999999999Z07:00'}}</code></td><td>2025-09-17T14:31:18.260445005Z</td></tr><tr><td>Kitchen</td><td><code>{{now '' '3:04PM'}}</code></td><td>2:31PM</td></tr></tbody></table>

## Using offsets

When using template helper method `now`, time offset must be formatted using the following syntax.

| Shorthand | Type        |
| --------- | ----------- |
| ns        | Nanosecond  |
| us/µs     | Microsecond |
| ms        | Millisecond |
| s         | Second      |
| m         | Minute      |
| h         | Hour        |
| d         | Day         |
| y         | Year        |

Prefix an offset with `-` to subtract the duration from the current date time.

### Example time offset

| 5m    | 5 minutes        |
| ----- | ---------------- |
| 1h30m | 1 hour 5 minutes |
| 1y10d | 1 year 10 days   |

### Examples

RFC1123Z +1 day = {{now '1d' 'Mon, 02 Jan 2006 15:04:05 -0700'}}\
RFC1123Z -1 day = {{now '-1d' 'Mon, 02 Jan 2006 15:04:05 -0700'}}\
RFC1123Z +5mins = {{now '5m' 'Mon, 02 Jan 2006 15:04:05 -0700'}}\
RFC1123Z -5mins = {{now '-5m' 'Mon, 02 Jan 2006 15:04:05 -0700'}}\
RFC1123Z +1h30min = {{now '1h30m' 'Mon, 02 Jan 2006 15:04:05 -0700'}}\
RFC1123Z -1h30min = {{now '-1h30m' 'Mon, 02 Jan 2006 15:04:05 -0700'}}\
RFC1123Z +1y10d = {{now '1y10d' 'Mon, 02 Jan 2006 15:04:05 -0700'}}\
RFC1123Z -1y10d = {{now '-1y10d' 'Mon, 02 Jan 2006 15:04:05 -0700'}}


# Conditional logic

You can control logic within your template using a number of conditional statements including:

* `{{#if } {{else}} {{/if }}` - this checks for the existence of something (this does not check equality)
* `{{#unless}} {{else}} {{/unless}}` - this checks for the non-existence of something (this does not check non-equality)
* `{{#equal}} {{else}} {{/equal}}` - this checks equality, i.e. if something equals something

Example 1:

```handlebars
{{#if (Request.QueryParam.price) }}
	A price of {{ Request.QueryParam.price }} was provided

	{{#equal Request.QueryParam.price "10"}}
    		Price is 10!
	{{else}}
		Price is something other than 10.
  	{{/equal}}
{{else}}
	No price was provided
{{/if}}
```

Example 2:

```handlebars
{{#unless Request.QueryParam.product}}
	No product was provided
{{else}}
	A product named "{{Request.QueryParam.product}}" was provided
{{/unless}}
```

Follow a tutorial [here](https://docs.cloud.hoverfly.io/create-simulations/using-templating-in-simulations/pages/oqKMVrUTaD0DLKTqOi7U#part-3.-conditional-statements) to learn more about conditionals and equality


# Looping over arrays

Learn how to loop over arrays in Hoverfly Cloud simulations using templating to dynamically generate responses.

The ability to loop over arrays of data can be very useful in constructing a response. Some of the arrays typically in a response are:

* the elements of path
* the headers in the request
* an array of query parameters if there are more than one with the same name
* a JSON array extracted from the body of a request

The following block is used to loop over an array. If there are no items then the else block will execute:

* `{{#each}} {{else}} {{/each}}`

The following block is used to return the first item from an array. If there are no items then the else block will execute:

* `{{#first}} {{else}} {{/first}}`

You can use the `@index`, `@key` and `this` keywords to determine the index, key and value of the object under the iterator. You can use `@last` keyword to determine if the current object is the last one in the array.

### Example 1:

```handlebars
{{#each Request.Header}}
	{{@index}} : {{@key}} : {{this}}
{{else}}
	No Request Headers were provided
{{/each}}
```

### Example 2:

Using looping and conditional logic you can build our a JSON (or XML) response:

Given the following request body

```json
{
    "people": [
        {
            "name": "John",
            "surname": "Doe",
            "age": 30
        },
        {
            "name": "Jane",
            "surname": "Lee",
            "age": 29
        }
    ]
}
```

And creating the following simulation body template

```json
{ "ages":
    [
        {{#each (Request.Body 'JSONpath' '$.people') }}
        {{this.age}}
        {{#unless @last}},{{/unless}}
        {{/each}}
    ]
}
```

The result generated from the template and sent back in the body would be this:

```json
{
    "ages": [
        30,
        29
    ]
}
```

Follow a tutorial [here ](https://docs.cloud.hoverfly.io/create-simulations/using-templating-in-simulations/pages/oqKMVrUTaD0DLKTqOi7U#part-4.-iterating-over-request-collections)to learn more about looping


# Variables and Arrays

Work with variables and arrays in Hoverfly Cloud simulations using templating to create dynamic and flexible API responses.

#### Variables:

You can create a variable and put a value into it using the following function:

```handlebars
{{ putValue 'variablename' value outputtotemplate? }}
```

example:

```handlebars
{{ putValue 'id' (Request.Body 'jsonpath' '$.id') true }}
```

(The *outputtotemplate* boolean will determine if the value is written out to the template as well as stored in memory, or just stored in memory.)

You can read a variable and use it in another function, or simply render it into the template using the following function:

```handlebars
{{ getValue 'variablename' }}
```

example: simply rendering out:

```handlebars
{{ getValue 'price' }}
```

example: using within another function:

```handlebars
{{ add (getValue 'price') this.tax '0.00' }}
```

#### Arrays:

You can append items to an array using the following function: (this is useful within a loop when you need to sum a list of numbers at the end)

```handlebars
{{ addToArray 'arrayname' value outputtotemplate?}}
```

example:

```handlebars
{{ addToArray 'totalweight' (multiply (this.quantity) (csv 'products' 'upc' 'this.upc' 'weight') '') false}}
```

(The *outputtotemplate* boolean will determine if the value is written out to the template as well as appended to the array, or just appended to the array.)

You would generally not render an array straight into the template - they would typically be used by another function or block statement that takes arrays, using the following function:

```handlebars
{{ getArray <arrayname> }}
```

example: passing into another function:

```handlebars
{{ sum (getArray 'totalweight') '0.00' }}
```

example: adding a new column to an in memory csv data store:

```handlebars
{{ addToArray 'newPet' '2000' false }} 
{{ addToArray 'newPet' 'dogs' false }} 
{{ addToArray 'newPet' 'Violet' false }} 
{{ addToArray 'newPet' 'sold' false }}

{{ csvAddRow 'pets' (getArray 'newPet') }}
```


# Arithmetic operations

You can perform simple addition, subtraction, multiplication and division between any two numbers using the following functions.

Note that these functions can be embedded into other functions.

That means they will return the result, either directly into the template for rendering as part of the response, or if they are enclosed in another function, then the result will be returned into that function.

### Addition

```handlebars
{{ add  <number1> <number2> <format>}}
```

example:

```handlebars
{{ add this.cost this.markup '0.00' }}
```

###

### Subtraction

```handlebars
{{ subtract <number1> <number2> <format> }}
```

example:

```handlebars
{{ subtract this.fullprice this.discount '0.00' }}
```

###

### Multiplication

```handlebars
{{ multiply <number1> <number2> <format> }}
```

example:

```handlebars
{{ multiply this.quantity this.price '0.00' }}
```

###

### Division

```handlebars
{{ divide <number1> <number2> <format> }}
```

example:

```handlebars
{{ divide this.discount '10' '0.00'}}
```

###

### Summing Arrays

You can also sum an array of numbers using the following function:

```handlebars
{{ sum <array> <format> }}
```

example 1:

```handlebars
{{ sum (split (Request.Body 'jsonpath' '$.price[*]') ' ') '0.00' }}
```

example 2:

```handlebars
{{ sum myArrayOfNumbers '0.00' }}
```


# String operations

You can use the following helper methods to join, split, replace or perform substring operations on string values.

| **Description**                                                                               | **Example**                                                                                                                                              | **Result**               |
| --------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ |
| String concatenate                                                                            | {{ concat 'bee' 'hive' }}                                                                                                                                | beehive                  |
| Convert a delimited string into an array                                                      | {{ split 'bee,hive' ',' }}                                                                                                                               | \[]string{“bee”, “hive”} |
| <p>Replace all occurrences of the old value with the new</p><p>value in the target string</p> | <p>{{ replace (Request.Body 'jsonpath' '$.text')</p><p>'be' 'mock' }}</p><p>(where Request.Body has the value of</p><p>{"text":"to be or not to be"}</p> | to mock or not to mock   |
| Return a substring of a string                                                                | {{substring 'thisisalongstring' 7 11}}                                                                                                                   | long                     |
| Return the length of a string                                                                 | {{length 'thisisaverylongstring'}}                                                                                                                       | 21                       |
| Return the rightmost characters of a string                                                   | {{rightmostCharacters 'thisisalongstring' 3}}                                                                                                            | ing                      |


# Validation operations

You can use the following helper methods to validate various types, compare value, and perform regular expression matching on strings.

| **Description**                          | **Example**                                                                                                  | **Result** |
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------ | ---------- |
| Is the value numeric                     | {{isNumeric '12.3'}}                                                                                         | true       |
| Is the value alphanumeric                | {{isAlphanumeric 'abc!@123'}}                                                                                | false      |
| Is the value a boolean                   | <p>{{isBool (Request.Body 'jsonpath' '$.paidInFull')}}</p><p>Where the payload is {“paidInFull”:”false”}</p> | true       |
| Is one value greater than another        | <p>{{isGreaterThan (Request.Body 'jsonpath' '$.age') 25}}</p><p>Where the payload is {“age”:”19”}</p>        | false      |
| Is one value less than another           | <p>{{isLessThan (Request.Body 'jsonpath' '$.age') 25}}</p><p>Where the payload is {“age”:”19”}</p>           | true       |
| Is a value between two values            | <p>{{isBetween (Request.Body 'jsonpath' '$.age') 25 35}}</p><p>Where the payload is {“age”:”19”}</p>         | false      |
| Does a string match a regular expression | {{matchesRegex '2022-09-27' '^\d{4}-\d{2}-\d{2}$'}}                                                          | true       |


# Simulating a persistent backend

Hoverfly Cloud supports two distinct mechanisms for simulating a persistent backend. Data sources, and Journal templating. Both of them depend on templating.

### CSV Data sources

You can upload up to 10 CSV files as data sources when editing your simulation from the Simulation tab.

This is configured at the simulation level, and the ability to store and retrieve tabular data within this data store is scoped at the service instance level.

You can both query data from a CSV data source as well as manipulate data within a data source by adding to it and deleting from it. Hoverfly supports a number of templating methods for simple read, update and delete functions. In addition Hoverfly supports a templating function that allows simple SQL like commands for SELECT, UPDATE and DELETE.

This is only available to enterprise customers.

You can read about this approach [here](/create-simulations/using-data-sources-in-simulations)

###

### Journal Templating

Hoverfly Cloud has the ability to retrieve from memory any past request that has been indexed with a key you provide, and then retrieve any part of that request or response for processing in your current response.

This is configured at the service instance level, and the ability to store and retrieve historical requests and responses is scoped at the service instance level.

This ability to look up in history, is one of the ways Hoverfly supports the mocking of a persistent back-end service. This is only available to enterprise customers.

You can read about this approach [here](/work-with-services/configuring-journal-indexing)


# Transitioning state between requests

Manage transitioning state between requests in Hoverfly Cloud simulations using templating for realistic API testing.

Hoverfly Cloud can utilise a state machine with variables that you set and form part of the matching of requests thus controlling how the simulation flows through states.

You can read about this approach in the Hoverfly documentation [here](https://docs.hoverfly.io/en/latest/pages/keyconcepts/state/state.html)


# Combining and nesting templating functions

Combine and nest templating functions in Hoverfly Cloud simulations for complex and dynamic API response generation.

With all functions that take parameters the convention is as follows:

* String literal parameters and number literal parameters are enclosed in single quotes.
* When calling a function from within a function the inner function should be enclosed in parenthesis (round brackets) not handlebars.
* When using variables and arrays, their names are string based parameters and are normally enclosed in single quotes, unless they are the result of a nested function (this can be useful)
* Boolean flag parameters are not enclosed in single quotes.
* Iterator instance parameters (this, or this.<\<some-variable>>) are not enclosed in single quotes
* Function names are not enclosed in single quotes.

#### Examples:

```handlebars
{{ putValue 'id' (Request.Body 'jsonpath' '$.id') true }}
{{ multiply '5' '2' '0.00' }}
{{ multiply this.quantity this.price '0.00' }}
```

Many functions can be nested inside other functions. In some cases it makes sense to nest multiple levels of functions. It is conventional to enclose the inner functions with round brackets instead of handlebars.

#### Example 1:

Consider the following 3 functions:

```handlebars
{{ sum <array> '<format>' }}
{{ split <delimited-string> '<delimiter>' }}
{{ Request.Body '<querylanguage>' '<query>' }}
```

As an example they can be combined together in the following way:

```handlebars
{{ sum(split (Request.Body 'jsonpath' '$.price[*]') ' ') '0.00' }}
```

#### Example 2:

Consider the following 3 functions:

```handlebars
{{ putValue '<variablename>' <value> <outputtotemplate?> }}
{{ multiply <number1> <number2> '<format>' }}
{{ csv '<data-source-name>' '<key-column>' '<key-value>' '<return-column>' }}
```

As an example they can be combined together in the following way:

```handlebars
{{ putValue 'linetotalsbeforediscounts' (multiply (this.quantity) (csv 'products' 'upc' 'this.upc' 'price') '') false}}
```

##


# Useful helper functions

Leverage useful helper functions within Hoverfly Cloud's templating engine to simplify and enhance your API simulations.

### Concatenate two strings

```handlebars
{{ concat '<string1>' '<string2>' }}
```

### Search and replace text in a string

```handlebars
{{ replace '<string-to-search>' '<string-to-replace>' '<replacement-string>' }}
```

### Create an array from a delimited string

This can be particularly useful when dealing with the results of a JSONPath query that returns an array, as these are space delimited strings of values.

```handlebars
{{ split '<delimited-string>' '<delimiter>' }}
```

### Change the HTTP response code

If you are following a pattern where you want a single request/response pair to return different HTTP response codes based on the outcome of logic, then you can do that using the following function:

```handlebars
{{ setStatusCode <any-valid-http-response-code> }}
```

### Set the value of an HTTP response header

You can set the value of an HTTP header dynamically from script:

```handlebars
{{ setHeader '<header-name>' '<new-value>'}}
```


# Avoiding HTML encoding in function return values

Prevent HTML encoding of function return values in Hoverfly Cloud templating to ensure correct formatting in your API responses.

By default the handlebars engine will HTML escape every value it returns into the template.

What this means is that if the value returned from any function contains one of the HTML special characters, then they will be replaced with their escaped equivalent.

| Character | Description       | Escaped Equivalent  |
| --------- | ----------------- | ------------------- |
| `&`       | Ampersand         | `&amp;`             |
| `<`       | Less than         | `&lt;`              |
| `>`       | Greater than      | `&gt;`              |
| `"`       | Double quote      | `&quot;`            |
| `'`       | Single quote      | `&apos;` or `&#39;` |
| `©`       | Copyright symbol  | `&copy;`            |
| `®`       | Registered symbol | `&reg;`             |
| `™`       | Trademark symbol  | `&trade;`           |

In order to avoid this behavior, you need to enclose the function in triple handlebar syntax.

for example:

```handlebars
{{faker 'Question'}} 
```

might return

```
You probably haven&apos;t heard of them?
```

where as, if used with triple handlebars:

```handlebars
{{{faker 'Question'}}} 
```

might return

```
You probably haven't heard of them?
```


# Using data sources in simulations

Hoverfly Cloud supports CSV data sources for Enterprise customers to do key value data lookups and simulate persistence within simulations.

### Attaching a data source to a simulation

You can upload a csv file when editing your simulation from the Simulation tab.

You can both query data from a CSV data source as well as manipulate data within a data source by adding to it and deleting from it. Hoverfly supports a number of templating methods for simple read, update and delete functions. In addition Hoverfly supports a templating function that allows simple SQL like commands for SELECT, UPDATE and DELETE.

Note that you cannot edit the data sources on a simulation already running on a service. You need to add and remove data sources from the master copy of the simulation, and then start a service running a copy of that simulation.

<div data-full-width="false"><figure><img src="/files/4Ds8Oab95QALmZbsACMM" alt=""><figcaption><p>Add CSV data sources</p></figcaption></figure></div>

### Looking up a data value from within the response template

To use the data in the csv file, you need to use the {{ csv }} templating function.

```handlebars
{{csv '<data-source-name>' '<key-column>' '<key-value>' '<return-column>'}}
```

So for example given a data source named "products" with the following csv structure:

<figure><img src="/files/KGc0RcY55PIvrEaZZHxJ" alt=""><figcaption></figcaption></figure>

You can use the following syntax to render the word "shirt" in a response template (note the use of single quotes):

```handlebars
{{csv 'products' 'productId' '101' 'productName'}}
```

Or if for example the productId was provided at position 1 on the path:

```handlebars
{{csv 'products' 'productId' (Request.Path.[1]) 'productName'}}
```

Or if you needed to loop over some JSON array of productIds from the request body and render back data doing lookups for each productId:

```handlebars
{{#each (Request.Body 'jsonpath' '$.products')}}  
ProductId {{this}} is {{csv 'products' 'productId' this 'productName'}}
{{/each}}
```

There are a number of functions to allow querying, updating, deleting and inserting data into the csv data sources. You can read more about them below:

[<mark style="color:yellow;">Querying csv data sources</mark>](/create-simulations/using-data-sources-in-simulations/querying-data-sources)

[<mark style="color:yellow;">Updating csv data sources</mark>](/create-simulations/using-data-sources-in-simulations/updating-data-in-data-sources)

[<mark style="color:yellow;">Deleting data from csv data sources</mark>](/create-simulations/using-data-sources-in-simulations/deleting-data-from-data-sources)

[<mark style="color:yellow;">Inserting data into csv data sources</mark>](/create-simulations/using-data-sources-in-simulations/inserting-data-into-a-data-source)

[<mark style="color:yellow;">Guidance on using the SQL like syntax</mark>](/create-simulations/using-data-sources-in-simulations/guidance-on-using-the-sql-like-syntax)


# Querying data sources

Hoverfly Cloud supports data queries from a CSV Data Source for Enterprise customers to do key value data lookups and simulate persistence.

### Reading from a CSV Data Source

You can read data from a CSV data source in a number of ways.

For illustration we will use this data source called "pets":

| id   | category | name    | status    |
| ---- | -------- | ------- | --------- |
| 1000 | birds    | Archie  | available |
| 1001 | dogs     | Zipper  | available |
| 1002 | dogs     | Teddy   | sold      |
| \*   | no data  | no data | no data   |

### Single value lookup with {{csv}}

The most basic query function is to return the value of one field (selected-column) given a field name to search (column-name) and a value to search for in that field (query-value). Of course the query-value would normally be pulled from the request.

Syntax:

```handlebars
{{csv 'data-source-name' 'column-name' 'query-value' 'selected-column' }}
```

Template Example: Display the Name of the pet with Id 1001

```handlebars
{{ csv 'pets' 'id' '1001' 'name' }}
```

Output:

```
Zipper
```

### More advanced examples: Single value lookup with {{csv}}

Template Example: Display the Name of the pet with Id taken from position 2 on the path

```handlebars
{{csv 'pets' 'id' 'Request.Path.[2]' 'name'}}
```

Template Example: Use conditional logic to check if a pet with Id taken from position 2 on the path exists, and if not return an error. Note that when the csv function is used within an #equal block, it needs to be enclosed in round brackets.

```handlebars
{{#equal (csv 'pets' 'id' 'Request.Path.[2]' 'name') 'no data'}}
    {{setStatusCode 404}}
{{else}}
.
.
{{/equal}}
```

###

### Retrieve all rows as a map with {{csvAsMap}}

Additional functions are available to query the CSV data source to return all or a filtered subset of it’s rows, as a map.

Retrieving the results as a map makes it simple to render back into the template, as you can use the {{this}} expression with the column names to identify which fields you want to render.

Note that as you will use this wrapped within an #each or #first block, the csvAsMap function must be enclosed inside round brackets.

See examples below.

Syntax:

```handlebars
{{csvAsMap 'data-source-name' }}
```

Template Example:

```handlebars
{
    "All-The-Pets": [ 
    {{#each (csvAsMap 'pets')}}
    {
        "id":{{this.id}}, 
        "category":"{{this.category}}", 
        "name":"{{this.name}}", 
        "status":"{{this.status}}"
    }
    {{#unless @last}},{{/unless}} 
    {{/each}} 
    ]
}
```

Output:

```json
{
    "All-The-Pets": [
        {
            "id": 1000,
            "category": "cats",
            "name": "Sylvester",
            "status": "available"
        },
        {
            "id": 1001,
            "category": "dogs",
            "name": "Zipper",
            "status": "available"
        },
        {
            "id": 1002,
            "category": "dogs",
            "name": "Teddy",
            "status": "sold"
        }
    ]
}
```

### Retrieve filtered rows as a map with {{csvMatchingRows}}

To filter the map on a single column value at the time of query you can use csvMatchingRows. This will return all the rows where the (column-name) = (query-value).

Note that as you will use this wrapped within an #each or #first block, the csvMatchingRows function must be enclosed inside round brackets.

```handlebars
{{csvMatchingRows 'data-source-name' 'column-name' 'query-value'}}
```

Template Example:

```handlebars
{
    "Dogs-Only": [ 
        {{#each (csvMatchingRows 'pets' 'category' 'dogs')}}
        {
            "id":{{this.id}}, 
            "category":"{{this.category}}", 
            "name":"{{this.name}}", 
            "status":"{{this.status}}"
        }
        {{#unless @last}},{{/unless}} {{/each}} 
        ]
}
```

Output:

```json
{
    "Dogs-Only": [
        {
            "id": 1001,
            "category": "dogs",
            "name": "Zipper",
            "status": "available"
        },
        {
            "id": 1002,
            "category": "dogs",
            "name": "Teddy",
            "status": "sold"
        }
    ]
}
```

### Advanced querying with SQL SELECT {{csvSqlCommand}}

A simplified SQL like syntax can be used to query the data in a csv data source and retrieve a map of the results. (This syntax can also be used to [UPDATE ](/create-simulations/using-data-sources-in-simulations/updating-data-in-data-sources)and [DELETE ](/create-simulations/using-data-sources-in-simulations/deleting-data-from-data-sources)from the data source. You cannot insert using this syntax however there is a mechanism which can be read about [here](/create-simulations/using-data-sources-in-simulations/inserting-data-into-a-data-source).)

Note that as you will use this wrapped within an #each or #first block, the csvSQLCommand must be enclosed inside round brackets.

You can read more about using this SQL like syntax [here](/create-simulations/using-data-sources-in-simulations/guidance-on-using-the-sql-like-syntax).

Syntax:

```handlebars
{{csvSqlCommand 'sql select, update or delete statement'}}
```

Template Example:

```handlebars
{
    "Dogs-With-Big-Ids-Only": [
    {{#each (csvSqlCommand "SELECT * FROM pets WHERE category = 'dogs' AND id >= '1002'")}}
        {
            "id":{{this.id}}, 
            "category":"{{this.category}}", 
            "name":"{{this.name}}", 
            "status":"{{this.status}}"
        }{{#unless @last}},{{/unless}}
    {{/each}}
    ]
}
```

Output:

```json
{
    "Dogs-With-Big-Ids-Only": [
        {
            "id": 1002,
            "category": "dogs",
            "name": "Violet",
            "status": "sold"
        }
    ]
}
```


# Updating data in data sources

With Hoverfly Cloud Enterprise you can update data within a CSV data source on the fly just as if your API were updating a real data source.

### Updating data in a CSV Data Source

You can update data within a CSV data source on the fly within your simulation just as if your API were updating a real data source. The data is modified for the duration that the service is running. When the service is restarted, the data will revert to what was in the original uploaded CSV.

For illustration we will use this data source called "pets":

| id   | category | name   | status    |
| ---- | -------- | ------ | --------- |
| 1000 | birds    | Archie | available |
| 1001 | dogs     | Zipper | available |
| 1002 | dogs     | Teddy  | sold      |

### Update data with {{csvSqlCommand}}

A simplified SQL like syntax can be used to update the data in a csv data source. (This syntax can also be used to [SELECT ](/create-simulations/using-data-sources-in-simulations/querying-data-sources)and [DELETE ](/create-simulations/using-data-sources-in-simulations/deleting-data-from-data-sources)from the data source. You cannot insert using this syntax however there is a mechanism which can be read about [here](/create-simulations/using-data-sources-in-simulations/inserting-data-into-a-data-source).)

You can read more about using this SQL like syntax [here](/create-simulations/using-data-sources-in-simulations/guidance-on-using-the-sql-like-syntax).

Syntax:

```handlebars
{{ csvSqlCommand 'sql-update-statement' }}
```

Template Example: Set the status of pets with a name of 'Archie' to 'sold'

```handlebars
{{ csvSqlCommand "UPDATE pets SET status = 'sold' WHERE name = 'Archie' }}
```

Result:

There is no output from an UPDATE statement but the data in memory for all subsequent calls to the API simulation will be modified as follows:

| id   | category | name   | status    |
| ---- | -------- | ------ | --------- |
| 1000 | birds    | Archie | sold      |
| 1001 | dogs     | Zipper | available |
| 1002 | dogs     | Teddy  | sold      |

###


# Deleting data from data sources

Delete CSV data source records on-the-fly within simulations with Hoverfly Cloud Enterprise - data is removed temporarily, reverting on restart.

### Deleting data from a CSV Data Source

You can delete data from a CSV data source on the fly within your simulation just as if your API were deleting data from a real data source. The data is removed for the duration that the service is running. When the service is restarted, the data will revert to what was in the original uploaded CSV.

There are two ways to delete data.

1. Using the {{csvDeleteRows}} function which will delete rows where a specified column matches a specified value
2. Using the {{csvSqlCommand}} function which allows you to use a SQL like syntax to issue a DELETE SQL command which allows more conditions to be matched than csvDeleteRows.

For illustration we will use this data source called "pets":

| id   | category | name   | status    |
| ---- | -------- | ------ | --------- |
| 1000 | birds    | Archie | available |
| 1001 | dogs     | Zipper | available |
| 1002 | dogs     | Teddy  | sold      |

### Method 1: Delete data with {{csvDeleteRows}}

This method deletes data where a column matches a value that you specify. It can also optionally return the number of rows deleted into the template, or into another function wrapping it.

Syntax:

```handlebars
{{csvDeleteRows 'data-source-name' 'column-name' 'query-value' output-result}}
```

Template Example: Delete all birds and don't return the count

```handlebars
{{ csvDeleteRows 'pets' 'category' 'birds' false }}
```

Result:

In this case there will be no output from csvDeleteRows but the data in memory for all subsequent calls to the API simulation will be modified as follows:

| id   | category | name   | status    |
| ---- | -------- | ------ | --------- |
| 1001 | dogs     | Zipper | available |
| 1002 | dogs     | Teddy  | sold      |

If the output-result flag had been set to true, then the function would have had the following output:

```
1
```

###

### Method 2: Delete data with {{csvSqlCommand}}

A simplified SQL like syntax can be used to delete the data in a csv data source. (This syntax can also be used to [SELECT ](/create-simulations/using-data-sources-in-simulations/querying-data-sources)and [UPDATE ](/create-simulations/using-data-sources-in-simulations/updating-data-in-data-sources)from the data source. You cannot insert using this syntax however there is a mechanism which can be read about [here](/create-simulations/using-data-sources-in-simulations/inserting-data-into-a-data-source).)

You can read more about using this SQL like syntax [here](/create-simulations/using-data-sources-in-simulations/guidance-on-using-the-sql-like-syntax).

Syntax:

```handlebars
{{ csvSqlCommand 'sql-delete-statement' }}
```

Template Example: Delete all dogs whose ids are greater than 1001

```handlebars
{{ csvSqlCommand "DELETE FROM pets WHERE category = 'dogs' AND id > '1001'" }}
```

Result:

There is no output from a SQL DELETE statement but the data in memory for all subsequent calls to the API simulation will be modified as follows:

| id   | category | name   | status    |
| ---- | -------- | ------ | --------- |
| 1000 | birds    | Archie | sold      |
| 1001 | dogs     | Zipper | available |

### s


# Inserting data into a data source

Insert new CSV data rows on-the-fly within simulations with Hoverfly Cloud Enterprise - data is added temporarily, reverting on restart.

### Inserting new data into a CSV Data Source

You can insert new data rows into a CSV data source on the fly within your simulation just as if your API were inserting data into real data source. The data is added for the duration that the service is running. When the service is restarted, the data will revert to what was in the original uploaded CSV.

For illustration we will use this data source called "pets":

| id   | category | name   | status    |
| ---- | -------- | ------ | --------- |
| 1000 | birds    | Archie | available |
| 1001 | dogs     | Zipper | available |
| 1002 | dogs     | Teddy  | sold      |

### Inserting data with {{csvAddRow}}

This method takes an array of strings as a parameter and adds them to the data source. You add to an array using the function {{addToArray}}. In the pets data source example there are 4 columns, and so you need to call it four times to create an array containing 4 strings.

The syntax for adding to, and reading from an array can be read [here](/create-simulations/using-templating-in-simulations/variables-and-arrays)

csvAddRow Syntax:

```handlebars
{{csvAddRow 'data-source-name' array-of-values}}
```

Template Example: Add a new dog to the data source

```handlebars
{{ addToArray 'newPet' '1003' false }} 
{{ addToArray 'newPet' 'dogs' false }} 
{{ addToArray 'newPet' 'Violet' false }} 
{{ addToArray 'newPet' 'available' false }}

{{ csvAddRow 'pets' (getArray 'newPet') }}
```

Result:

The new pet will be added to the pets data source in memory for all subsequent calls to the API simulation. It will be modified as follows:

| id   | category | name   | status    |
| ---- | -------- | ------ | --------- |
| 1000 | birds    | Archie | available |
| 1001 | dogs     | Zipper | available |
| 1002 | dogs     | Teddy  | sold      |
| 1003 | dogs     | Violet | available |

###


# Guidance on using the SQL like syntax

With Hoverfly Cloud Enterprise you can use SQL-like syntax for querying, updating and deleting from in-memory csv data sources.

### Supported SQL syntax

You can use a simplified SQL like syntax to select, update and delete rows.

### SQL Commands

* INSERT is not supported. To add data you must use the [csvAddRow ](/create-simulations/using-data-sources-in-simulations/inserting-data-into-a-data-source)template function.
* SELECT \[column-names] FROM \[data-source-name] WHERE \[conditions] (\* can be used to indicate all colmuns)
* UPDATE \[data-source-name] SET \[\[column-name] = ‘\[value]’,] WHERE \[conditions]
* DELETE FROM \[data-source-name] WHERE \[conditions]

### Conditions

* Only simple conditions are supported.
* You can chain conditions using AND. OR is not supported.
* The following comparison operators are supported in conditions:

\= equals

\> greater than

< less than

\>= greater than or equal to

<= less than or equal to

!= not equal to

### Other considerations

* Capitalization of SQL keywords is required.
* Spaces between components of the SQL statement are required.
* Every value provided to a condition whether a number or a string must be enclosed in quotes.
* Data source names must not be in quotes.
* Joins across different data sources are not supported..

### Examples

For illustration we will use this data source called "pets":

| id   | category | name   | status    |
| ---- | -------- | ------ | --------- |
| 1000 | birds    | Archie | available |
| 1001 | dogs     | Zipper | available |
| 1002 | dogs     | Teddy  | sold      |

```
SELECT * FROM pets WHERE category = 'dogs' AND id >= '1002'

SELECT name, status FROM pets WHERE category = 'birds'

UPDATE pets SET status = 'sold' WHERE name = 'Archie'

UPDATE pets SET status = 'sold', name = 'Name expunged' WHERE id > '10'

DELETE FROM pets WHERE category = 'dogs' AND id > '1001'
```


# Working with Simulation Files

Hoverfly Cloud stores the configuration of its API simulations in JSON simulation files.

One JSON file = One Hoverfly Simulation

This topic discusses

* how these files are stored in Hoverfly Cloud
* how they are applied to running services
* how to keep different versions of them synchronized
* how to upload and download them

### Terminology

* Services run instances of simulations.
* Services are running web servers and can be viewed from the Hoverfly Cloud dashboard
* Simulations are JSON files that represent an API simulation configuration - it's endpoints and matching configuration
* Simulation files are stored in a simulation library accessed from the menu in Hoverfly Cloud
* Simulations can be downloaded from, and uploaded to the simulation library
* Services can be started using a simulation file from the library. When started in this way they make their own copy of the simulation file and any changes made to it from within that service are independent of the master simulation file stored in the simulation library. In this way a single master simulation can be shared with many service instances which will each take their own copy.
* Services can also be started without a simulation file. In this case the service will have a simulation labelled (unsaved) when viewed from the dashboard.

### Considerations if you are running a service with an unsaved simulation

In this case the service will have a simulation labelled (unsaved) when viewed from the dashboard.

This implies that the simulation that the service is running does not have a master copy in the simulation library. It was started without a simulation, and any configuration done to the simulation in this service is only in this service and cannot be shared.

You need to follow the following steps to add the unsaved simulation to the simulation library before you can download it, or before it can be used by other services that might need to.

Step 1: Click on (unsaved) simulation

<figure><img src="/files/R9uXsrTlaD8zipLREdHA" alt=""><figcaption></figcaption></figure>

Step 2: Click down arrow and Export simulation as new

<figure><img src="/files/loMF94lqBJViVCSuYMjP" alt=""><figcaption></figcaption></figure>

Once you have exported the simulation it will appear in the simulation library from where it can be downloaded.

### Considerations if you are running a service with a simulation from the library

In this case the service will have a named simulation when viewed from the dashboard.

When the service was started, it was done so using a simulation file from the simulation library.

The version of the simulation running in the service is a separate copy of the master simulation file and can be changed independently of the simulation file stored in the library.

If you wish to keep the version running in the service separately from the version stored in the library you need to **export** is as a new simulation file, with a different name to the version already in the library.

<figure><img src="/files/6WkUiX1mFXYlLgPVuymc" alt=""><figcaption></figcaption></figure>

If you wish to overwrite the existing version in the library with any changes made to the version running in the service, you can **synchronize** the service's simulation with the library. This will overwrite what's in the library with what is currently in the service.

<figure><img src="/files/A5yaoGadWzslD0YEh5gn" alt=""><figcaption></figcaption></figure>

### Downloading simulations from the simulation library

Click the download icon next to the simulation from the simulation library.

<figure><img src="/files/7k7RDc3jjKL0Slco18lE" alt=""><figcaption></figcaption></figure>

### Uploading simulations to the simulation library

Click the Upload button from the simulation library

<figure><img src="/files/wY1TcNXn7T1H8Z9ZdZBX" alt=""><figcaption></figcaption></figure>


# Simulation Naming and Versioning

This guide helps you apply a consistent naming strategy to your simulations in Hoverfly Cloud

Hoverfly Cloud does not currently provide built-in version control, but by following these naming practices, you can manage simulations like code simply and effectively.

Simulations are stored in the Simulation Library from where they can be downloaded and because simulations are just JSON files, you can easily use a versioning tool like git to manage them outside the platform if required.

### Naming Convention

\
Use the following format for your simulation names: `{service-name}--{version}`

Examples:

| Simulation   | Version | Simulation Name            |
| ------------ | ------- | -------------------------- |
| user-service | v1      | user-service--v1           |
| user-service | v1.1    | user-service--v1.1         |
| payment-api  | testA   | payment-api--feature-testA |
| inventory    | dev     | inventory--dev-2025-07-24  |

You can use any of the following in the version part:

* v1, v2, v1.0.1 (semantic versioning)
* dev, staging, prod
* Feature identifiers: feature-X, bugfix-Y
* Dates: 2025-07-24

Recommended Practices

**DO:**

* Use consistent separators like -- to make parsing easier.
* Include version or context in every name.
* Use semantic versioning if you treat simulations like API contracts.
* Delete obsolete simulations to reduce clutter.
* Agree on naming rules up front
* Document your team’s naming rules in a README or internal wiki.

**DON’T:**

* Overwrite simulations without renaming, you’ll lose history.
* Use ambiguous names like temp1, test2, or new-sim.
* Rely on memory write down what each version is for.

### Example workflow: Creating a new version from an existing simulation

Download the Simulation that you want to clone and create a new version of:

<figure><img src="/files/3ahQG9MfgLGvS53irdv8" alt=""><figcaption></figcaption></figure>

Re-Upload the Simulation and give it a new version in the name

<figure><img src="/files/g1RlLxvOLD1ldnDlNfDA" alt=""><figcaption></figcaption></figure>

The simulation will now be cloned with a new version number in the Simulation Library:

<figure><img src="/files/DtvO1bO7tQ6ekNJSONzD" alt=""><figcaption></figcaption></figure>

### Example workflow: Creating a new version from a running simulation

Alternatively, if you have a simulation on a running service that you want to copy into the library you can do so by exporting the simulation to the library with a new name and version:

Click on the name of the running simulation from the dashboard

<figure><img src="/files/fiFrYfZxmxZCMMsGoCJr" alt=""><figcaption></figcaption></figure>

Then click Export simulation as new

<figure><img src="/files/9lncjo1Tbr2nhLL4rDp4" alt=""><figcaption></figcaption></figure>

And provide a new name and a version number

<figure><img src="/files/5IZOVRNHQ6livPwZveg4" alt=""><figcaption></figcaption></figure>

Lastly, once you have created a new version and applied whatever changes you need to, you will want to update your services to use the new version of the simulation:

Click on the service name from the dashboard and pick the version of the service that you wish to run.

<figure><img src="/files/bYP0jG32Cd2LUWXvBbMl" alt=""><figcaption></figcaption></figure>

Then select the new simulation from the drop down and it will immediately be applied to the service.

<figure><img src="/files/Ci5XIArSDsvEbhS67Clo" alt=""><figcaption></figcaption></figure>

Optionally delete or archive the older version if no longer needed.

###


# Service

Hoverfly Cloud simulates HTTP services like web APIs and SOAP, providing API simulations, test doubles, and configurable HTTP stubs.

Hoverfly Cloud services simulates real HTTP services such as web APIs and SOAP services. You can think of Hoverfly Cloud services as API simulations, over the wire test doubles, or more highly configurable HTTP stubs and mocks.

Hoverfly Cloud uses our Open Source tool, [Hoverfly](https://github.com/SpectoLabs/hoverfly) to simulate a service. Hoverfly Cloud uses Kubernetes to run and manage multiple copies of Hoverfly, and adds a powerful GUI with many additional capabilities.

The Service in Hoverfly Cloud refers to a running instance of Hoverfly with a loaded Simulation file. The Simulation file represents the configuration for the Service, how it will match incoming HTTP requests, and how it will respond when it makes a match.

##


# Start a new service

Start a new service in Hoverfly Cloud to create and manage API simulations for testing and development of reliable API interactions.

Starting a service creates a public available HTTP service that simulates an API. Click on “Add” in the Dashboard to start a new service.

You can select a simulation from the dropdown which will be imported when the service starts, and you need to add a label to identify your service from the Dashboard later on.

Click “OK”, and your service should be up and running within a few seconds.

## Enable proxying

You can enable proxying when starting a new service. Proxying allows the service to forward requests to a remote destination. You specify the base URL of the remote destination in the `Target URL` field. You can select one of the following proxy modes:

* Simulate: simulate API response based on simulation
* Spy: similar to simulate, but call the real service if a request is not matched
* Capture: requests will go to the real service and all the interactions will be captured.
* Passthrough: bypass Hoverfly service, and get response from the real service. This lets you switch from using virtual service to real service without restarting your app with different configurations.

## Add behaviors (for Pro/Enterprise account)

A Hoverfly Behavior is a function that intercepts and modifies the API response before it returns to the client. With Behaviors, it is possible to introduce bad responses, latency model and more to mimic real world behavior of an API which is otherwise hard to reproduce.

Currently Hoverfly Cloud supports these predefined Behaviors:

* Random status code
* Find and replace
* Compress response
* Set response headers
* Simulate latencies

You can add a Behavior from the (+) sign to the right of the service in the Dashboard.

<figure><img src="/files/Z6K9GjYWrmmtwQ6xYL0f" alt=""><figcaption></figcaption></figure>

Click on the toggle next to the Behavior name, for example “Random status code”, select status code you want it to return, and use the slider to change the probability of this status code.

<figure><img src="/files/kZ8kkEObMyQxmXMM9lRQ" alt=""><figcaption></figcaption></figure>

You can add additional entries. Probabilities that total over one will get sampled down. When the probability total is less than one, the left over probability is used for the original status code.


# Use a service

Use an authenticated service in Hoverfly Cloud. Requests require an API token (create one on the Account page).

## Use an authenticated service

Sending a request to an authenticated service requires an API token. Please create one from the Account page. We would recommend you to export it as an environment variable.

To authenticate your access to the service, an request must contains an authentication header:

```
curl -H "X-Hoverfly-Authorization: Bearer $HFC_TOKEN" SERVICE_URL
```

In your project, you may not want to change your code to use Hoverfly Cloud. You can use the Hoverfly Cloud command line tool `hcc` to handle the authentication, and you can call your Hoverfly Cloud service like a localhost service.

```
hcc reverse-proxy start --name SERVICE_NAME --api-token $HFC_TOKEN
```

Once you run the above command, the service would be available on <http://localhost:8500>

## View service details and journal

The journal logs every request and response that Hoverfly Cloud sees so it is useful for troubleshooting, analysis and monitoring. The journal page provides a number of filters to allow you to home in on errors and particular entries.

You can click on the service name to open up the service details page. It gives you information about the service, such as launch time, mode, URL, and target URL etcs.

You can also view the journal which is a request log of the service. A green entry indicates a successful match and a red entry indicates a failed match.


# Update a service

Update an existing service in Hoverfly Cloud to modify your API simulations, add new functionality, and adapt to evolving testing requirements.

## Change simulations

You can update your service to use a different simulation stored in your account.

Go to service detail pages, and select the simulation name from the dropdown.

Hoverfly Cloud will take care of updating the simulations in the service.

## View and edit running simulations

Click on the simulation link to view the simulations loaded in the service.

You can make change to it using the editor, and click “Apply changes” to make your change effective.

## Export running simulations

You can also export the simulation in an active service for future sharing or reuse, especially the simulations are created via capturing.

Click on the dropdown menu in the toolbar and select “Export simulation as new\...”, it will prompt you for the simulation name.


# Configuring Journal Indexing

This provides the useful illusion of a persistent back-end.

### Configuring Journal Indexing on a Service (for Enterprise accounts)

This feature gives the user the ability to retrieve any part of a previously received request, or served response on the same service, and render it.

This provides the useful illusion of a persistent back-end. It uses it's in-memory journal which is a history of previous requests/responses processed, to achieve this illusion, hence this templating function's name {{ journal }}

As an example, this will give you the ability to have a POST or PUT endpoint which takes a product with a specific ID and then for example a GET endpoint on the same service which will retrieve the previously stored product based on it's ID and respond with it.

<figure><img src="/files/bW5bWAWKNAqW04Zoe6kI" alt=""><figcaption></figcaption></figure>

In the above example the service is told to index the journal based on the productId in the request body’s json.

When the first PUT request is made containing a productid and productDescription, Hoverfly stores the Request/Response pair in the journal and gives it an index key of 1.

Later on the client makes a GET to a different endpoint with the number 1 stored in the path at zero based index position 2. The template responds by calling the journal templating function, and telling it to use the index on the productId, and to retrieve the Request/Response pair using the index value that was passed in.

Once retrieved it renders the productDescription from the Response, using a jsonPath query.

Selecting the Edit Journal Indexing menu item from the ellipse to the right of the service on the Dashboard brings up the Configure Journal Indexing modal:

<figure><img src="/files/ZqovlCMzm3DBt3RBLTAq" alt=""><figcaption></figcaption></figure>

This capability is achieved through Hoverfly Cloud indexing all previous requests and responses according to a key that you provide, which identifies a part of a request. In the above example it is a query parameter called productId. Other valid examples might be:

`Request.Body 'jsonpath' '$.productId'` (If your request has a json element called productId in the body)

`Request.Body 'xpath' '//root/productId'` (If your request has an xml element called productId in the body)

A templating function is provided which then allows you to render any part of a previous request or response according to that key. The function is structured as follows:

```handlebars
{{ journal <request-index> <key-value-to-search-for> <request-or-response?> <query-type> <query-to-execute> }}                    
```

Here are a couple of examples of using the {{ journal }} function:

#### Example 1: Note the use of single quotes and brackets as required:

* \<request-index> <mark style="color:blue;">'Request.Body jsonpath $.productId'</mark> - the literal string is passed in
* \<key-value-to-search-for> <mark style="color:blue;">(Request.Path.\[1])</mark> - this is a function therefore enclosed in ( )
* \<request-or-response> <mark style="color:blue;">'Response'</mark> - the literal string is passed in
* \<query-type> <mark style="color:blue;">'jsonpath'</mark> - the literal string is passed in
* \<query-to-execute> <mark style="color:blue;">'$.productDescription'</mark> - the literal string is passed in

```json
{
  "productDescription": "{{ journal 'Request.Body jsonpath $.productId' (Request.Path.[1]) 'Response' 'jsonpath' '$.productDescription' }}"
}
```

#### Example 2: Similarly, note that strings are enclosed in quotes and functions in ( )

<pre class="language-xml"><code class="lang-xml"><strong>&#x3C;?xml version="1.0" encoding="UTF-8"?>
</strong>&#x3C;productDescription>{{ journal 'Request.Body xpath //productId' (Body.Request 'xpath' '//productId') 'Response' 'xpath' '//productDescription' }}&#x3C;/productDescription>
</code></pre>

### Important Considerations

The journal templating feature uses an in-memory history of the previous 1000 requests and corresponding responses processed by the API. The oldest requests are purged from memory once more than 1000 requests are processed. Thus to work correctly, your dataset must not exceed a maximum of 1000 unique items when using journal templating.


# Command line interface

Use the Hoverfly Cloud command-line interface (CLI) to manage your API simulations and virtual services from the terminal.

`hcc` is a multi-purpose command line interface for Hoverfly Cloud. It provides a convenient way to manage your Hoverfly Cloud virtual services and automate their management. Either for ad-hoc actions via the command line or integrated into scripts that are used by Continuous Integration and DevOps tools such as Jenkins.

You can capture traffic within your network and publish the simulation to your account with `hcc`.

See the [Reference page](/hoverfly-cloud-cli/hoverfly-cloud-cli) for a full list of commands.

## **Download**

* [MacOS 64bit](https://github.com/hoverflycloud/hcc/releases/latest/download/hoverfly-cloud-cli-darwin-amd64.zip)
* [Windows 64bit](https://github.com/hoverflycloud/hcc/releases/latest/download/hoverfly-cloud-cli-windows-amd64.zip)
* [Windows 32bit](https://github.com/hoverflycloud/hcc/releases/latest/download/hoverfly-cloud-cli-windows-386.zip)
* [Linux 64bit](https://github.com/hoverflycloud/hcc/releases/latest/download/hoverfly-cloud-cli-linux-amd64.zip)
* [Linux 32bit](https://github.com/hoverflycloud/hcc/releases/latest/download/hoverfly-cloud-cli-linux-386.zip)

## **Installation**

Download the correct version using the links above. Unpack the zip file and you are good to go.

You may copy the unpacked binary to `/usr/local/bin` (for Mac and Linux), so that you can run `hcc` without specifying the full path.

Verifying the installation by running

```
hcc version
```

It should print out the version, such as `v2.0.0`

## **Getting started**

After you download and install the CLI, [create an API token](https://cloud.hoverfly.io/account) on the Account page.

Run the following command to configure `hcc` to authenticate with your account:

```
hcc config set api-token {your API token}
```

The API token is stored in `~/.hcc/config.yaml` for future use.

## Start a service

Launch a virtual service from the command line:

* Using a local simulation file.

```
hcc service start my-service --simulation-file FILE_NAME
```

* Or using a simulation created on Hoverfly Cloud.

```
hcc service start my-service --simulation-name SIMULATION_NAME
```

## Update the simulation

Update the simulation data on a service:

* Using a local simulation file.

```
hcc service update my-service --simulation-file FILE_NAME
```

* Or using a simulation created on Hoverfly Cloud.

```
hcc service update my-service --simulation-name SIMULATION_NAME
```

## Reset a service

You can wipe the simulation data, journal and states by reseting the service:

```
hcc service reset my-service
```

## Delete a service

Delete a service from the command line:

```
hcc service delete my-service
```

If your service contains simulation data that is not saved, it will be lost. You may want to [export the simulation](#export-a-simulation) first.

## Start a capture service

Launch a Hoverfly Cloud service to capture a remote API from the command line:

```
hcc service start my-service --mode capture --target-url https://example-api.com
```

You should pass the base URL of the API to the `--target-url` flag.

## Update the proxy mode

If you have started a service with proxy enabled by setting the `--target-url` and `--mode` . You can switch the mode using the following command:

```
hcc service update my-service --mode spy
```

[See here](/work-with-services/start-a-new-service#enable-proxying) for a list of available proxy modes.

## Export a simulation

Export the simulation data from a service to a new simulation resource on your Hoverfly Cloud account:

```
hcc service export my-service --simulation-name SIMULATION_NAME
```

Your service must be running, and the SIMULATION\_NAME must not conflict with an existing name.


# Hoverfly Cloud CLI commands

Explore the Hoverfly Cloud CLI commands to manage your API simulations and virtual services directly from your command line.

This page contains the output of

```
hcc --help
```

```
Command line interface for Hoverfly Cloud

Usage:
  hcc [command]

Available Commands:
  capture            Commands for interacting with local capture proxy
  config             Get/set CLI config properties
  help               Help about any command
  reverse-proxy      Commands for interacting with local reverse proxy proxying to Hoverfly Cloud
  scenario           Commands for interacting with Hoverfly Cloud Scenarios
  service            Commands for interacting with Hoverfly Cloud Services
  simulation         Commands for interacting with Hoverfly Cloud Simulations
  version            Get the version of Hoverfly Cloud CLI

Flags:
      --api-token string   API token from Hoverfly Cloud
      --domain string      Domain name of Hoverfly Cloud
  -h, --help               help for hcc
      --insecure           Allow reverse proxy to private Hoverfly Cloud deployment without certs

Use "hcc [command] --help" for more information about a command.
```


# Quickstart

Quickstart guide for Hoverfly Cloud.  Learn how to quickly set up and start using Hoverfly Cloud for API simulation and testing.

## Start a virtual service from an example simulation

You can start your first virtual service with a pre-loaded [example simulation file](https://github.com/hoverflycloud/hcc/releases/latest/download/example-simulation.json) by following these steps:

1. On your [Dashboard](https://cloud.hoverfly.io/dashboard), click the "Add" button. An "Add service" dialog box will pop up.
2. Enter a service name, for example `my-test-service`.
3. Select `example-simulation` from the drop down and click "Confirm".

Hoverfly Cloud provisions a dedicated Hoverfly container and assigns a DNS name for your service (in the form of `<service-name>-<id>.hoverfly.io`). The service is ready to use when the green tick-mark appears next to the service in the dashboard.

Click on the allocated URL, and you should see the following screen.

![](/files/-Lf-9cII72qUYXQJ8LZS)

Congratulations! You have now got a highly configurable virtual service that you can share and use wherever you want.

If you look at the [Dashboard](https://cloud.hoverfly.io/dashboard), you will see that the test service is running and using the example simulation:

<figure><img src="/files/mqaZybyIdDU5LGDoXYDn" alt=""><figcaption></figcaption></figure>

If you open the example-simulation by clicking on the simulation "example-simulation", you can then edit the endpoints to make the API simulation do whatever you please.

1. From within the simulation editor, click Add endpoint, and then change the new endpoint to respond to Get methods.
2. Add a Path Request matcher, so that this endpoint will respond to a path of `/myapi/*` using a Glob match - which is a wildcard. So any path that starts with `/myapi/` will match.
3. Add a response body of `Hello {{ Request.Path.[1] }}`
4. Make sure to click Enable templating. This will allow Hoverfly to process the commands in the `{{ handlebar }}` syntax.
5. Your simulation should be configured as in the image below. Click Apply changes, and you will be returned to the Dashboard.
6. Now go back to the allocated URL, and add a path of `/myapi/<your-name-here>`
7. You should get a greeting from your API

<div data-full-width="true"><figure><img src="/files/YNJWhzeidKFLTeWfthfd" alt=""><figcaption><p>Add a custom endpoint and request matcher</p></figcaption></figure></div>


# Creating simulations and services

There are three main workflows to create new Simulations in Hoverfly Cloud. These tutorials will step you through the basics of each method, from creating the Simulation, to running the Service:

Tutorial 1: [Create a service and simulation manually](/tutorials/creating-simulations-and-services/tut1)

Tutorial 2: [Create a service and simulation by importing from a Swagger specification](/tutorials/creating-simulations-and-services/tut2)

Tutorial 3: [Create a service and simulation by capturing real API traffic](/tutorials/creating-simulations-and-services/tut3)


# Tutorial 1: Create a service and simulation manually

In this walkthrough you will create a virtual product API using the editor that exposes two HTTP GET endpoints; one that returns a json product for a given Id, and one that returns a list of products.

## Part 1. Setup the Simulation file with a GET product for a given productId Request/Response pair

Follow these steps:

1. Navigate to [Simulations](https://cloud.hoverfly.io/simulation).
2. Click Create
3. Click "Add endpoint"
   * This immediately creates a simple endpoint that matches any HTTP verb and responds with a status of 200 - OK.
4. Change the Method to GET
5. Change the Path to Regex match and enter /product/\[^/]+ in the textbox.

   * This will make the simulation respond when it receives a request that has a path ending in /product/\[some value here]
   * \[some value here] in this case will be the Id of the product that was sent as part of the request. You will use this later.

   <figure><img src="/files/c0H4SQ9pfZYLb3EdqOA1" alt=""><figcaption></figcaption></figure>
6. Add the following snippet to the Response Body:

   ```json
   {
       "productId": "{{ Request.Path.[1] }}",
       "name": "Fund {{ randomStringLength 1 }}",
       "price": {{ randomFloatRange 1.0 50.0 }}
   }
   ```
7. Click the Enable Templating checkbox. This will make Hoverfly parse the Response and replace the handlebar syntax {{ }} with values based on the expression used.

   <figure><img src="/files/uKL1VEjdfeexnELN7nog" alt=""><figcaption></figcaption></figure>
8. Scroll to the top of the page and click Save
9. Provide the name "product-sim" when prompted for a name
10. You will be returned to the Simulations page where your new simulation will appear in the list. From here using the buttons on the right, you can edit it, download it (useful if you wanted to manually edit the file, or store it in source control), and delete it.

## Part 2. Setup the Service

Follow these steps:

1. Navigate to the Dashboard
2. Click the orange +Add button in the Services section, this will open a dialogue window.
3. From the Simulation drop-down choose the "product-sim" simulation file that was just created
4. In the Name type "product". You will notice that this prefixes your unique hoverfly.io URL and will be the endpoint for this service.

   <figure><img src="/files/Qy7TsjYNdLqaDaxR5cha" alt=""><figcaption></figcaption></figure>
5. Leave the rest of the defaults and click Confirm
6. You will be returned to the dashboard, and if all went ok your new service will be spinning up. When it is ready it will have a green tick next to it.

   <figure><img src="/files/9r6jROFjkwqmP8RIJt22" alt=""><figcaption></figcaption></figure>
7. Copy the URL of the service - it will be something like <https://product-_youraccounthere_.hoverfly.io>
8. Open the URL in a browser, cURL or Postman and append the path /product/12345
9. The result should be some json generated from the Response template you set up earlier. For example:

   ```json
   {
       "productId": "12345",
       "name": "Fund a",
       "price": 10.587209
   }
   ```
10. You will notice that the productId is taken from the Request Path variable that you used in the Request. The name and price, were randomly generated using templating functions.
11. If you refresh you will get different values for the each of the name and price values.
12. If you change the path variable, it will be reflected in the Response as the productId
13. If you remove the path variable, you will notice that you receive a matching error from Hoverfly. It was not able to find a suitable Response match, given the Request provided.

## Part 3. Add another GET Request/Response pair to the same simulation file to return all Products

Follow these steps:

1. The service you created in step 2 runs a copy of the master simulation file you created in step.
2. If you were to make changes to the simulation file at the service level, it will not automatically update the master simulation file stored under "Simulations". You can however "Sync" any changes you make to the simulation at the service level back to the master simulation file, which will overwrite the master simulation file with your changes. You will do that now.
3. From the dashboard find the product service you created and click the Simulation link for the service. This will open the simulation editor with simulation that the service is running. Because you are opening the service's copy of the simulation, and not the original master copy, you will see this message:

   <figure><img src="/files/vlHZ7KdEEuUyf9SqPNRI" alt="" width="563"><figcaption></figcaption></figure>
4. In the editor that opens you will see the single end point " GET/product/\[^/]+ "
5. You can either click +Add endpoint to add a new endpoint, or in this case we will simply duplicate the existing endpoint and make changes to it.
6. Click the ellipse next to the existing endpoint and choose "Duplicate". A new replica of the endpoint is created beneath the existing one.

   <figure><img src="/files/reeyOoFCguHH95zvQbz9" alt="" width="563"><figcaption></figcaption></figure>
7. This new endpoint will return a list of products and won't take any parameters, so change the Path under Request matches to an exact match with a Path of "/products"

   <figure><img src="/files/BQ3Xe1EfgfjAPBTvREPx" alt=""><figcaption></figcaption></figure>
8. Now change the Response Body of the new endpoint to the following json:

```json
[
    {
        "productId": "P001",
        "name": "Fund A",
        "price": 9.99
    },
    {
        "productId": "P002",
        "name": "Fund B",
        "price": 19.99
    },
    {
        "productId": "P003",
        "name": "Fund C",
        "price": 14.99
    },
    {
        "productId": "P004",
        "name": "Fund D",
        "price": 24.99
    },
    {
        "productId": "P005",
        "name": "Fund E",
        "price": 29.99
    }
]
```

9. We are not using Templating in this Response, so it can be unchecked. If you wanted to add templating you would simply check it.
10. Scroll up to the top of the page and click Apply changes. This will update the running service with the changes you have just made.
11. Now, if you navigate back to the Dashboard, you can copy the URL for the service and open it in a browser, cURL or Postman. This time append the path "/products" to the URL. You should get back your list of products as a response.
12. If you change the path from "/products" to "/product/abc", you should still get back a single product with productId abc.

## Part 4. Update the master simulation with the local changes

Follow these steps:

1. In order to keep the master simulation file in sync with the changes you have just made, you can update the master simulation by selecting "Sync simulation" from the drop down under the "Apply changes" button at the top of the service simulation editor.

   <figure><img src="/files/FqGRnJlCDNzkXZREGLTA" alt="" width="430"><figcaption></figcaption></figure>
2. Alternatively, you could also export your changes as a new simulation from here if that were the need.

## Part 5. Remove the service and simulation

Follow these steps:

1. Unless you want to keep the service and simulation, they can be deleted.
2. To delete the service and it's copy of the simulation navigate to the Dashboard, open the ellipse to the right of the product service that you created, and select Delete.
3. To delete the master simulation, navigate to the Simulations page, locate the simulation you created, and click the corresponding x at the right of page.

Congratulations! You have completed this Tutorial, "Create a Service and Simulation manually."


# Tutorial 2: Create a service and simulation by importing from a Swagger specification

In this walkthrough you will create a virtual pet store API by uploading a Swagger v2 specification document, that exposes 20 endpoints; of which we will explore 3:

* An HTTP GET that returns a pet for a given petId
* An HTTP GET that returns an array of pets matching a list of provided statuses
* An HTTP POST that creates a new user with the supplied data

## Part 1. Upload the Swagger file

Follow these steps:

1. Download the sample Swagger file to your computer from: <https://petstore.swagger.io/v2/swagger.json>
2. Navigate to the Simulations section and click the From Swagger button.
3. In the subsequent dialogue box name the simulation petstore-swagger-sim, locate the file and click Confirm.
4. You will be presented with the list of simulations and should see the new simulation at the top of the list. Click the edit button to open the simulation editor.
   * Note that this is the master simulation file. Once a new service is started from the main dashboard and this simulation is chosen, the new service will take a copy of this simulation, and any changes made at the service level will not automatically be synchronized with this master version.
5. From the editor you can see the 20 endpoints imported from the swagger document.
6. At this point we can spin up a service and this simulation will work.

## Part 2. Start a new service with the petstore-swagger-sim

Follow these steps:

1. Navigate to the main dashboard.
2. Click on +Add under services.
3. Select petstore-swagger-sim as the simulation to use.
   * Note that if you are part of an organization and you doing this tutorial alongside other members of the same organization, you will need to locate the version of the simulation under your name in the drop-down list.
4. Name the service petstore. This will prefix the URL for your unique service with petstore.
5. Leave the rest of the defaults as they are and click Confirm.
6. Once the orange blinking spot turns green, the service is running is can be tested from cURL, a web browser or Postman.
7. Copy the URL for the service and paste it in a web browser. If you make the request with just the base URL Hoverfly will return a matching error as it was not able to match your request with any the Request/Response pairs it has generated for the simulation from the Swagger file.

## Part 3. Test the GET /v2/pet/\[^/]+ endpoint

Follow these steps:

1. Append /v2/pet/10 to the end of the url so that it looks something like this: <https://petstore-_youraccount_.hoverfly.io/v2/pet/10>

   * Hoverfly will match the request to the closest Request matcher it has which is GET/v2/pet/\[^/]+ and will return the response it has stored which will be:

   ```json
   {
       "id": 0,
       "category": {
           "id": 0,
           "name": "string"
       },
       "name": "doggie",
       "photoUrls": [
           "string"
       ],
       "tags": [
           {
               "id": 0,
               "name": "string"
           }
       ],
       "status": "available"
   }
   ```

## Part 4. Test the GET /v2/pet/findByStatus endpoint

Follow these steps:

1. Now we can try another GET which returns an array of pets given a status. This Request matcher requires a path of exactly /v2/pet/findByStatus, and then a query parameter called status with a value. The query should look something like https\://petstore-*youraccount.*&#x68;overfly.io/v2/pet/findByStatus?status=somestatus

   * When executing this request, the response will be the following:

   ```json
   [
       {
         "id": 0,
         "category": {
           "id": 0,
           "name": "string"
         },
         "name": "doggie",
         "photoUrls": [
           "string"
         ],
         "tags": [
           {
             "id": 0,
             "name": "string"
           }
         ],
         "status": "available"
       }
     ]
   ```
2. These canned responses are correct in structure, but may not reflect actual values in the test system. If that is required they can easily be replaced by editing them in the simulation editor for the service.
3. Navigate to the simulation for the service by going to the dashboard, and then clicking the Simulation named petstore-swagger-sim for the petstore service under the Services section.
4. Once in the simulation editor, click the "GET/v2/pet/findByStatus" endpoint (it might be on the 2nd page of endpoints) and scroll down to the response section. Here we can edit the json Response if that response needed to be generated in some custom way. We can also enable templating via the checkbox, and make the status value return what was inputted as a querystring parameter for status using handlebar syntax. Remember to click "Apply changes" to save the modified simulation to the running service.

   ```json
   [
       {
         "id": 1,
         "category": {
           "id": 1,
           "name": "dogs"
         },
         "name": "Woofles",
         "photoUrls": [
           "image/woofles.jpg"
         ],
         "tags": [],
         "status": "{{ Request.QueryParam.status }}"
       },
       {
           "id": 2,
           "category": {
             "id": 2,
             "name": "cats"
           },
           "name": "Simba",
           "photoUrls": [
               "image/simba.jpg"
             ],
           "tags": [],
           "status": "{{ Request.QueryParam.status }}"
         }
     ]
   ```
5. Test this endpoint from the browser, cURL or Postman including the following path and querystring to your service URL "GET/v2/pet/findByStatus?status=pending", and the above json should be returned but with the handlebar template functions having been replaced with the word "pending".

## Part 5. Test the POST /v2/user endpoint

Follow these steps:

1. Locate and click on the POST /v2/user endpoint to open it's properties.
2. This endpoint is for the creation of a new user by supplying a json object with the user details in the Request body.
3. From the Swagger file, the Request has been set to respond to exact matches of the Request body to a json object conforming to the schema and values specified in the Swagger document for a user. So in order for Hoverfly to recognize and respond to a POST to this endpoint, that exact json must be supplied, which might not be the behavior you need when creating a simulation that needs to respond to variable data in the POST's Request body.
4. The current JSON Matcher looks for this exact JSON to be present:

   ```json
   {
       "id": 0,
       "username": "string",
       "firstName": "string",
       "lastName": "string",
       "email": "string",
       "password": "string",
       "phone": "string",
       "userStatus": 0
   }
   ```

   Where as it might make more sense to change the Matcher to a Glob matcher with a value of \* for the body, in which case any body sent would be a positive match and a response returned.
5. Navigate to the simulation editor for the service, locate the Request matcher's Body, and change the it from an Exact match to a Glob match for \*

   <figure><img src="/files/1dALP8KQgjg3igReTPik" alt=""><figcaption></figcaption></figure>
6. Remember to click "Apply changes" at the top of the screen to save your changes to the running service.
7. You won't be able to test from a browser as we need to do a POST, so with Postman set up the endpoint to POST to <https://petstore-_youraccount_.hoverfly.io/v2/user>. You can put anything you like in the body.
8. Hit the endpoint and you should receive a 200 OK status response with no body.
9. Change the Response body to include something more meaningful, for example the json below, apply the changes, and test that it works no matter what you put into the Request body:

   ```json
   {
       "message": "success"
   }
   ```

## Part 6. Simulating Errors

Follow these steps:

1. We now have a POST that simulates successful user creations. But what if we wanted the API to occasionally return an error to ensure that the caller's error handling is working correctly. To do that we can introduce Behaviors into the running service.
2. Navigate to the Dashboard and locate the petstore service under Services.
3. Click the + sign to the right of the service and click it to bring up the Behavior configuration screen.
4. Let's add a 405 error to occur 50% of the time.

   <figure><img src="/files/98SMv7KZjY5ChmM9pTHC" alt=""><figcaption></figcaption></figure>
5. Now when we test the POST endpoint from Postman, you will notice that the service sometimes returns a 200 OK, and the rest of the time a 405 Method Not Allowed.
6. There are a number of other behaviors that you can experiment with including latency and replacing text in the Response with something else.

## Part 7. Remove the service and simulation

Follow these steps:

1. Unless you want to keep the service and simulation, they can be deleted.
2. To delete the service and it's copy of the simulation navigate to the Dashboard, open the ellipse to the right of the product service that you created, and select Delete.
3. To delete the master simulation, navigate to the Simulations page, locate the simulation you created, and click the corresponding x at the right of page.

Congratulations! You have completed this Tutorial, "Create a service and simulation by importing from a Swagger specification."


# Tutorial 3: Create a service and simulation by capturing real API traffic

In this walkthrough you will capture then virtualize a currency exchange API which exposes one endpoint that returns currency exchange rate  information.

* In the first few parts you will create a simulation file by recording a set of real requests and their resultant responses that you will make to the real API.
* You will then take the recorded request/response pairs and manipulate them to create an API simulation that behaves like the real thing but returns synthetic data.

## Part 1. Explore the API we will capture and then simulate

Follow these steps:

1. Using your API client or browser, make a call to the following (fictitious) API to get the exchange rates between USD and other major currencies:

   <https://8fkvh431u4.execute-api.eu-west-2.amazonaws.com/api/currencies?currency=USD>
2. The data returned shows the (fictitious) conversion rates between the provided querystring parameter (USD) and other currencies, as well as the time that the call was made:

```json
{
    "exchangerates": [
        {
            "name": "GBP",
            "rate": 1.2731
        },
        {
            "name": "EUR",
            "rate": 1.0928
        },
        {
            "name": "USD",
            "rate": 1
        },
        {
            "name": "JPY",
            "rate": 0.007
        },
        {
            "name": "CHF",
            "rate": 1.1131
        },
        {
            "name": "CAD",
            "rate": 0.7558
        },
        {
            "name": "AUD",
            "rate": 0.6768
        },
        {
            "name": "NZD",
            "rate": 0.6168
        },
        {
            "name": "RUB",
            "rate": 0.0118
        },
        {
            "name": "ZAR",
            "rate": 0.0545
        },
        {
            "name": "MXN",
            "rate": 0.0582
        },
        {
            "name": "AED",
            "rate": 0.2723
        }
    ],
    "timeofquote": "2023-07-05T08:38:07"
}
```

3. Note that this data is not current, but for the purposes of this walkthrough, we will pretend this is a real currency API with real data.
4. The API works with the following values for currency: GBP,EUR,USD,JPY,CHF,CAD,AUD,NZD,RUB,ZAR,MXN,AED, if you try and pass in anything else you will get a response something like {"exchangerates":null,"timeofquote":"2023-07-05T10:39:07"}

## Part 2. Start up a Hoverfly instance as a proxy to the real API

Follow these steps:

1. To create a Simulation by recording the behavior of the API, navigate to the Dashboard and click +Add under Services to add a new service.
2. Leave Simulation blank as we don't yet have one. We are going to create a new simulation by capturing the activity of the real API with our service in capture mode.
3. Enter "currencies" as the Name of the service. You will notice that this will show you what the new simulated service endpoint will be, something like `https://currencies-xxxxxxx.hoverfly.io`
4. Leave the cluster size at 1 pod
5. Check Enable proxying:
   * For the Target URL enter the scheme and hostname, but leave off the path of the API URL that we want to capture. In this case it is: <https://8fkvh431u4.execute-api.eu-west-2.amazonaws.com>
   * If the API used a port other than 443 or 80 we would need to add it to the end, e.g. :8080
   * For Mode, select "capture"
   * Leave the rest of the checkboxes unchecked and click Confirm

     <div data-full-width="false"><figure><img src="/files/muV0EYfRtRlRrCJdy8Ka" alt=""><figcaption></figcaption></figure></div>
6. You are returned to the Dashboard and your new service will be blinking as it starts up a Hoverfly instance which will be listening for requests at the address you can find under the URL column for the Service.

## Part 3. Capture a request/response pair from the real API

Follow these steps:

1. Call the Hoverfly instance in the same way that you called the real API in part 1 of this walkthrough, however now we are calling Hoverfly, and it will capture and then pass the request on to the real API, which will pass the response back through Hoverfly which will again capture the response before passing back to us:
   * Append /api/currencies?currency=USD to the URL copied from the list of Services and execute it from your API client or browser. It will be something like: `https://currencies-xxxxxx.hoverfly.io/api/currencies?currency=USD`
   * (replace the xxxxxx in the subdomain with your accounts unique string)
2. The data returned will be exactly as it was from the real API, however it has passed through Hoverfly and created a Simulation.
3. Change the Mode from "capture" to "simulate" in the dropdown for your currencies service from the dashboard, and execute that same end point again:
   * `https://currencies-xxxxxx.hoverfly.io/api/currencies?currency=USD` (replace the xxxxxx in the subdomain with your accounts unique string)
   * The exact same results will be returned, however they are now being returned from Hoverfly, and the real API is no longer being hit.

## Part 4. Explore the newly created Simulation

Follow these steps:

1. From the Dashboard, click the link that says (unsaved) under Simulation for your currencies Service in the service list.
2. You will be taken to the simulation editor for your running currencies service.
3. On the left you will see each of the endpoints generated from Hoverfly when it was in capture mode.
4. There will be a GET /api/currencies endpoint
   * If you sent the request from your browser, you may also see a /favicon.ico request. You can delete that.

     <figure><img src="/files/J6EFhqxXerHQiZ6Pyrwo" alt=""><figcaption></figcaption></figure>
5. Highlight the GET /api/currencies endpoint and on the right you will see the various settings that can be configured for this Request/Response pair, they are:
   1. Stateful settings
      * These allow you to create a simulation that keeps state between requests and can respond differently to identical requests depending on the state
   2. Request Matchers
      * Hoverfly will try to match requests sent to it, in order to find the best matched response to return.
      * In this case, while your Hoverfly service was in capture mode earlier, it recorded all of these values:
        * the method was a GET
        * the destination was exactly "8fkvh431u4.execute-api.eu-west-2.amazonaws.com"
        * the path was exactly "/api/currencies"
        * the query string contained one parameter called currency and the simulation has configured this matcher to look for values exactly equal to USD.
        * There was no header or body recorded in the request.
      * All of these values in the Request matcher, can be manipulated to configure Hoverfly to match requests based on combinations of exact values, Glob (\*) matches, or regular expressions
   3. Response
      * This is the HTTP response that Hoverfly will return if the configuration of the Request matchers (above) are satisfied. Here you can modify the Response including:
        * the status code
        * header keys and values
        * the response body
      * You can also make it return synthesized data, or data taken from parts of the Request, by using Templating.

## Part 5. Change the Request matcher to play back the same response no matter what currency is passed in

Follow these steps:

1. Currently the simulation only works if USD is passed in as a currency. If you try and pass in anything else you will get a matching error, as it is only configured to respond to USD.
2. Let's change that so that it always returns a response no matter what value is passed in for currency.
3. In the Request matchers section, under Query where is one parameter - currency:
   * Change the matcher type from "Exact match" to "Glob match"
   * Change the value from USD to \*
   * Click Apply changes at the top of the page.

     <figure><img src="/files/CZ7bjp4C0ChgoQzJHSjB" alt=""><figcaption></figcaption></figure>
4. Now if you re-hit the endpoint but instead use a currency of "monopolymoney", you will still get the same response.

## Part 6. Change the Response to provide random synthesized data

Follow these steps:

1. Navigate to the (unsaved) simulation.
2. Scroll down to the very bottom and check the "Enable templating" checkbox in the Response section.
3. Now replace the existing Response Body consisting of static exchange rates with the following which will generate random exchange rates and return the current date and time:

```json
{
    "exchangerates": [
      {
        "name": "GBP",
        "rate": {{ randomFloatRange 0.1 1.3 }}
      },
      {
        "name": "EUR",
        "rate": {{ randomFloatRange 0.1 1.3 }}
      },
      {
        "name": "USD",
        "rate": {{ randomFloatRange 0.1 1.3 }}
      },
      {
        "name": "JPY",
        "rate": {{ randomFloatRange 0.1 1.3 }}
      },
      {
        "name": "CHF",
        "rate": {{ randomFloatRange 0.1 1.3 }}
      },
      {
        "name": "CAD",
        "rate": {{ randomFloatRange 0.1 1.3 }}
      },
      {
        "name": "AUD",
        "rate": {{ randomFloatRange 0.1 1.3 }}
      },
      {
        "name": "NZD",
        "rate": {{ randomFloatRange 0.1 1.3 }}
      },
      {
        "name": "RUB",
        "rate": {{ randomFloatRange 0.1 1.3 }}
      },
      {
        "name": "ZAR",
        "rate": {{ randomFloatRange 0.1 1.3 }}
      },
      {
        "name": "MXN",
        "rate": {{ randomFloatRange 0.1 1.3 }}
      },
      {
        "name": "AED",
        "rate": {{ randomFloatRange 0.1 1.3 }}
      }
    ],
    "timeofquote": "{{ now '' '' }}"
  }
  
```

4. Apply the changes, you will get a warning that your changes will create inconsistencies between the Content-Length header and the response body. For now remove the Content-Length header.

   <figure><img src="/files/q2ZnjIWTV6naei42K3PF" alt=""><figcaption></figcaption></figure>
5. Now try hitting the endpoint a few times over in the browser or from your API client, and you will see random data being returned from the simulation.

## Part 7. Save the captured and edited simulation as a shareable Simulation

Follow these steps:

1. So far we have captured a request/response to and from the API using Hoverfly Cloud in capture mode, and after editing it a bit we played it back in Simulation mode.
2. This simulation is however local to the service in which it is running. You will have noticed that under the Simulation column on the dashboard, there is the word (Unsaved). In order to create a shareable copy of the simulation, we need to save it as a new Simulation whereafter it will appear in the Simulations area and can be copied and reused by other services as required.
3. Navigate to the simulation editor for this service by clicking on (Unsaved).
4. Now open the menu under the Apply changes button and select "Export simulation as new" and give it a name like "currencies-sim"

   <figure><img src="/files/Sty0daLYRHLIBIB221LP" alt="" width="450"><figcaption></figcaption></figure>
5. After saving it you will be able to find the simulation in the Simulations section of the website.
6. It is important to note that if you create a new service and have it use this newly created simulation, the service will make itself a copy of the master simulation. Changes made to the copy need to be explicitly synched back to the master if that is required. This is in order to allow different teams, developers or testers, to make their own personalized changes to simulations as required.

## Part 8. Remove the service and simulation

Follow these steps:

1. Unless you want to keep the service and simulation, they can be deleted.
2. To delete the service and it's copy of the simulation navigate to the Dashboard, open the ellipse to the right of the product service that you created, and select Delete.
3. To delete the master simulation, navigate to the Simulations page, locate the simulation you created, and click the corresponding x at the right of page.

Congratulations! You have completed this Tutorial, "Create a service and simulation by capturing real API traffic."


# Response Templating

Learn to uses the various types of response templating to modify the response.

Tutorial 4: [Response Templating](/tutorials/response-templating/tut4)


# Tutorial 4: Response Templating

In this walkthrough you will create a simple API simulation which uses various types of response templating to modify the response.

* Response Templating in Hoverfly Cloud makes use of {{handlebar}} syntax to give your response access to variables sent in the request, perform equality logic, and perform conditional logic in structuring your response.
* Hoverfly Cloud supports templating as described here: [Using templating in simulations](/create-simulations/using-templating-in-simulations)
* In this tutorial we will create a service and configure it's simulation to support a single GET method that uses response templating.

## Part 1. Start up a new service and configure a GET method

Follow these steps:

1. Navigate to the Dashboard
2. Click the orange +Add button in the Services section, this will open a dialogue window.
3. Leave the Simulation field blank: we will create a Simulation directly on this service.
4. In the Name type "response-templating". You will notice that this prefixes your unique hoverfly.io URL and will be the endpoint for this service.

   <figure><img src="/files/CMYkammEj6MHV8bTI3PL" alt=""><figcaption></figcaption></figure>
5. Leave the rest of the defaults and click Confirm
6. You will be returned to the dashboard, and if all went ok your new service will be spinning up. When it is ready it will have a green tick next to it.
7. Now let's configure a simple GET method on the /myapi path.
   1. Click on the (unsaved) simulation link for this service.
   2. You will be sent to the simulation that is unique to this service.
   3. Click on +Add endpoint and modify the Request matcher to look for a GET method and with an Exact match of /myapi
   4. For the Response, add some simple text in the Body

      <figure><img src="/files/343BbfkxbZTMySNfSKit" alt=""><figcaption></figcaption></figure>
8. Click Apply Changes at the top of the page to save the simulation.
9. Test the your service is working. Check the path to the GET method you have configured in your API client. (The URL can be copied from the Dashboard, it will be something like: `https://response-templating-xxxxxxx.hoverfly.io` and remember to append `/mapapi` to the end.

## Part 2. Extracting values from the Request

Follow these steps:

1. Hoverfly can re-use values from the Request path, query string, headers and body. You can also use jsonpath or xpath to query the Request body which we won't cover here.
2. From the Dashboard, Navigate to the (unsaved) simulation for the service
3. Replace the response body with the block below. Make sure you enable templating at the bottom of the page.

   ```handlebars
   [1. CHECK THE PATH]
   The path of the request is {{Request.Path}}
   {{#equal Request.Path "lucky"}}You hit the lucky path!{{/equal}}
   ```
4. This script will return the path used in the Request, as well as returning a specific block of text if the path is equal to "lucky".
5. Hoverfly's templating can perform simple equality checks to evaluate Request variables against strings, and then execute the statements contained within the {{#equal}} {/equal} block.
6. Save the simulation at the top of the page, and then test the GET endpoint again. You should receive a response:

   ```handlebars
   [1. CHECK THE PATH]
   The path of the request is myapi
   ```
7. We are not getting the "You hit the lucky path!" message. Even if you change the path in your API client to end in /lucky, you will get a matching error from Hoverfly. This is because our request matcher is looking for an Exact Path match for /myapi.
8. To fix this, change the Path's Exact match to a Glob match as follows:

   <figure><img src="/files/CXtr2tGeGTxeSFubpnSz" alt=""><figcaption></figcaption></figure>
9. Remember to click Apply changes. Now you can try `https://response-templating-xxxxxxx.hoverfly.io` and append `/lucky` to the end. You should receive the response:

   ```handlebars
   [1. CHECK THE PATH]
   The path of the request is lucky
     You hit the lucky path!
   ```

## Part 3. Conditional Statements

Follow these steps:

1. Hoverfly can use simple conditional statements (`#if` and `#unless`) to check for the presence of variables in the request, and it can perform simple equality checks (`#equal`) to establish if a variable is equal to a particular string.
2. From the Dashboard, Navigate to the (unsaved) simulation for the service
3. Add the block below to the the Response Body beneath what's already there, and then Apply Changes:

   ```handlebars
   [2. CHECK FOR QUERY PARAMETERS]
   {{#if (Request.QueryParam.price) }}
   	A price of {{ Request.QueryParam.price }} was provided
   	[3. CHECK EQUALITY]
   	{{#equal Request.QueryParam.price "10"}}
       		Price is 10!
     	{{/equal}}
   {{else}}
   	No price was provided
   {{/if}}
   ```
4. Resubmit the same GET query as before, without any query string: `https://response-templating-xxxxxxx.hoverfly.io/lucky`
5. You should receive the following:

   ```handlebars
   [1. CHECK THE PATH]
   The path of the request is lucky
     You hit the lucky path!

   [2. CHECK FOR QUERY PARAMETERS]
   	No price was provided	
   ```
6. Now try it again using a price of 10 and a price of 15 to check the various logic paths: `https://response-templating-xxxxxxx.hoverfly.io/lucky?price=10` `https://response-templating-xxxxxxx.hoverfly.io/lucky?price=15` - You will notice that the `#if` statement checks for the presence of a variable only, it cannot check that the variable is equal or not equal to something or execute any other type of operator.
7. You can also perform conditional logic inversely using the `{{#unless}} {{/unless}}` statement if this makes more sense in your scenario. This would be the equivalent of "Not If". Add the block below to the the Response Body beneath what's already there, and then Apply Changes:

   <pre class="language-handlebars"><code class="lang-handlebars"><strong>[4. USING UNLESS]
   </strong>{{#unless Request.QueryParam.product}}
   	No product was provided
   {{else}}
   	A product named "{{Request.QueryParam.product}}" was provided
   {{/unless}}
   </code></pre>
8. Now execute the end point with and without a product variable in the query string: `https://response-templating-xxxxxxx.hoverfly.io/lucky?product=apples` `https://response-templating-xxxxxxx.hoverfly.io/lucky`

## Part 4. Iterating over request collections

Follow these steps:

1. Hoverfly can iterate through the query string parameters and the headers that were sent in the Request. At the same time it can perform simple equality logic and conditional logic.
2. Add the block below to the the Response Body beneath what's already there, and then Apply Changes:

   ```handlebars
   [5. LOOP THROUGH HEADERS]
   {{#each Request.Header}}
   	{{@index}} : {{@key}} : {{this}}
   {{else}}
   	No Request Headers were provided
   {{/each}}
   ```
3. Execute the endpoint once again and you will receive all of the headers sent with the request, their index, key and value.
4. Now let's add conditional logic to a loop. Add the block below to the the Response Body beneath what's already there, and then Apply Changes:

   ```handlebars
   [6. CHECK EQUALITY WITHIN A LOOP]
   {{#each Request.QueryParam}}
   	{{@index}} : {{@key}} : {{this}} {{#equal this "10"}} The {{@key}} query parameter has a value of 10!{{/equal}}
   {{else}}
   	No Query Prameters were provided
   {{/each}}
   ```
5. The block above will loop through and print each variable in the query parameter list, and it will print out a message for any that have a value of 10.
6. Now execute the end point with and without a variable in the query string with a value of 10:
   1. `https://response-templating-xxxxxxx.hoverfly.io/lucky?product=apples&quantity=5` results in:

      ```handlebars
      [6. CHECK EQUALITY WITHIN A LOOP]
      	0 : product : apples 
      	1 : quantity : 5 
      ```
   2. `https://response-templating-xxxxxxx.hoverfly.io/lucky?product=apples&quantity=10` results in:

      ```handlebars
      [6. CHECK EQUALITY WITHIN A LOOP]
      	0 : product : apples 
      	1 : quantity : 10  The quantity query parameter has a value of 10!
      ```

## Part 5. Helper methods

Follow these steps:

1. Try and use some of the various helper methods to see how they work. You can learn how to use all these methods by starting to read from here: [Render back any part of the Request](/create-simulations/using-templating-in-simulations/render-back-any-part-of-the-request)
2. As a quick reference:

   <figure><img src="/files/wrB7kAYcudQaq0YsrFUg" alt=""><figcaption></figcaption></figure>

Congratulations! You have completed this Tutorial, "Response Templating."

There is a whole lot more that you can do that is not covered in this tutorial. Please have a look at the topic [Response Templating in Simulations](/create-simulations/using-templating-in-simulations) to read more.


# Hoverfly service modes

Hoverfly Cloud Services can run on 4 different modes, this tutorial will describe each of the modes and when to use them.

Tutorial 5: [Simulate, Capture, Spy and Passthrough modes](/tutorials/hoverfly-service-modes/tut5)


# Tutorial 5: Simulate, Capture, Spy and Passthrough modes

In this walkthrough you will work with each of the 4 Hoverfly modes to understand what they are used for.

* Hoverfly has various modes which we will use against [worldtimeapi.org](http://worldtimeapi.org/) :
  * Capture: To act as a proxy to an existing real HTTP API, whereby any requests made via the proxy and returned via the proxy are recorded into a simulation.
  * Simulate: To act as a webserver to serve up a pre-configured simulation consisting of pre-recorded or coded HTTP request/response pairs. In addition in Simulation mode, Hoverfly can adopt different matching strategies and use a combination of response templating and behavior injection to simulate realistic data and physical API behaviors.
  * Spy: To act primarily as a webserver exactly as in Simulate mode, but, if the matching strategy cannot find a response to match a given request, to then act as a passthrough proxy to the real service and return the actual API response.
  * Passthrough: To act as if it isn't there. Purely for convenience, this mode will pass all requests and responses straight to the real API and back to the caller for when you want to use the real API without having to reconfigure the environment.

## Part 1. Capture mode

Follow these steps:

1. Using your API client or browser, make a call to the following real API to get the current date and time for London:

   <http://worldtimeapi.org/api/timezone/Europe/London>
2. The data returned shows the real time and date in the BST timezone:

```json
{
    "abbreviation": "BST",
    "client_ip": "151.230.54.226",
    "datetime": "2023-08-16T11:08:00.896767+01:00",
    "day_of_week": 3,
    "day_of_year": 228,
    "dst": true,
    "dst_from": "2023-03-26T01:00:00+00:00",
    "dst_offset": 3600,
    "dst_until": "2023-10-29T01:00:00+00:00",
    "raw_offset": 0,
    "timezone": "Europe/London",
    "unixtime": 1692180480,
    "utc_datetime": "2023-08-16T10:08:00.896767+00:00",
    "utc_offset": "+01:00",
    "week_number": 33
}
```

3. Now configure a Hoverfly Cloud service in capture mode to record requests and responses to and from this API:
4. Click +Add service from the Dashboard.
5. Leave Simulation blank (we will be recording a Simulation in capture mode), give it a name of worldtimeapi, check enable proxying and provide a Target URL of <https://worldtimeapi.org>. Make sure to set the Mode to capture.

   <figure><img src="/files/7l5wEhPD8cxNcgke6Dct" alt=""><figcaption></figcaption></figure>
6. You will be returned to Dashboard and your new service will be blinking orange as the service is deployed. Once green, it is ready to be used.
7. Using your API client or browser, make a call to the new Hoverfly service in capture mode to get the current date and time for London:
   * `https://worldtimeapi-<<your unique id>>.hoverfly.io/api/timezone/Europe/London`
   * In doing so the request will be proxied through the Hoverfly service, recorded, and when the response comes back that will also be recorded.
8. Now click the (unsaved) link for the Simulation associated with your new service from the Dashboard.
   * You will see the simulation that was recorded, because the Hoverfly service was running in capture mode.
   * It will consist of one GET request method, and various fields showing Request matchers as well as the associated response for this request/response pair in the simulation.
   * At this point you could save the new simulation (Export simulation as new) from the simulation screen for this service, whereby it would appear in the Simulations section, and could be shared with your team for use in their Hoverfly services, or downloaded and kept in a source repository.

## Part 2. Simulate mode

Follow these steps:

1. Return to the Dashboard and switch the running worldtimeapi service from `capture` to `simulate` mode via the dropdown.
2. Once again using your API client or browser, make a call to the Hoverfly service in simulate mode to get the current date and time for London:
   * `https://worldtimeapi-<<your unique id>>.hoverfly.io/api/timezone/Europe/London`
   * In doing so the request will be served by the Hoverfly service, not proxied through to the real service. The real service is out of the picture.
   * Of course in our case, this does mean that every request (with the matching Request matchers) will be returned by the Hoverfly service with exactly the same response and the time won't change.
3. Now change the last segment of the path to Paris
   * `https://worldtimeapi-<<your unique id>>.hoverfly.io/api/timezone/Europe/Paris`
   * Now, because the Hoverfly service is in simulate mode, and it cannot match the path as the matcher has been configured, you will receive a matching error.
4. At this point you could fiddle with the simulation, duplicate and edit the request/response pairs that the simulation will serve, match based on glob or regular expressions, add templating to make it return the real time, inject delays into the simulation, or add other behaviors to the running service to simulate errors or change headers. You have control over the responses that Hoverfly Cloud will serve based on the request matchers that you set for a request/response pair.

## Part 3. Spy mode

Follow these steps:

1. Spy mode is Simulate mode, with the addition that if a request cannot be matched, instead of returning a matching error, the Hoverfly service will instead do a passthrough proxy of the request to the real service, and return the real result to the caller.
2. Return to the Dashboard and Change the worldtimeapi's mode to `spy`from the dropdown.
3. Once again using your API client or browser, make a call to the Hoverfly service, now in spy mode, to get the current date and time for London:
   * `https://worldtimeapi-<<your unique id>>.hoverfly.io/api/timezone/Europe/London`
   * Because it found a match, the request will be served by the Hoverfly service, not proxied through to the real service. The time will still show the time in the past that was stored when the response was captured in Part 1.
4. Now change the last segment of the path to Paris
   * `https://worldtimeapi-<<your unique id>>.hoverfly.io/api/timezone/Europe/Paris`
   * Now, because the Hoverfly service is in spy mode, and it cannot match the request as it has been configured, it will pass the request on to the real service and the response should come back with the real time for Paris.
5. With Spy mode it is possible to switch between the simulated service and the real service by setting a matching strategy that will purposefully mismatch based on a header or parameter that you set in the request, should you want to control which calls must go through and be served by the real service, and which should be served by the Hoverfly simulation.

## Part 4. Passthrough mode

Follow these steps:

1. Passthrough mode will simply pass all requests through to the real service without attempting to perform matching.
2. Return to the Dashboard and Change the worldtimeapi's mode to `passthrough` from the dropdown.
3. Now try various combinations of paths including the one that has a matching request matcher (/Europe/London) and you will note that the response is always returned from the real service no matter what.

## Part 5. Remove the service

Follow these steps:

1. Unless you want to keep the service, they can be deleted.
2. To delete the service and it's copy of the simulation navigate to the Dashboard, open the ellipse to the right of the product service that you created, and select Delete.

Congratulations! You have completed this Tutorial, "Tutorial 4: Simulate, Capture, Spy and Passthrough modes."


# Automating with the CLI and API

Use the command line interface and the API to automate the creation and configuration of simulated APIs for use in your CI/CD pipelines.

Tutorial 6: [Using the CLI and the Hoverfly Cloud API](/tutorials/automating-with-the-cli-and-api/tut6)


# Tutorial 6: Using the CLI and the Hoverfly Cloud API

In this walkthrough you will use the Hoverfly Cloud command line interface, to start a service from the command line. You will then use the Hoverfly Cloud API to modify the behavior of the service.

* `hcc` is a multi-purpose command line interface for Hoverfly Cloud. It provides a convenient way to manage your Hoverfly Cloud virtual services and automate their management. Either for ad-hoc actions via the command line or integrated into scripts that are used by Continuous Integration and DevOps tools such as Jenkins.

  You can also capture traffic within your network and publish the simulation to your account with `hcc`. You can read more about that [here](/hoverfly-cloud-cli).
* The Hoverfly Cloud API provides full control over your services, simulations and scenarios, as well as giving you access to the journal, service statistics and behaviors.

## Part 1. Prepare the environment

Follow these steps:

1. Install the CLI for your operating system by following the steps outlined [here](/hoverfly-cloud-cli).
2. Create a simple Hoverfly Simulation with a single endpoint by following step 1 in [Tutorial 1: Create a service and simulation manually](/tutorials/creating-simulations-and-services/tut1). Do not create the service, only the simulation.
3. Once the simulation is created. Navigate back to the [Dashboard](https://cloud.hoverfly.io/dashboard).

## Part 2. Start a Service from the hcc CLI

Follow these steps:

1. If you followed the previous steps you should have a saved simulation called product-sim. Now we will start a service that uses that simulation.
   * Execute the following hcc command from the command line to start a service called product with that product-sim simulation.

     ```
     hcc service start product --simulation-name product-sim
     ```
   * If you refresh your [Dashboard ](https://cloud.hoverfly.io/dashboard)you will see a new service with the name product starting up.
2. Test the running service by hitting the single endpoint with your API client: `https://product-`*`youraccounthere`*`.hoverfly.io/product/12345`
3. You can remotely manipulate services, simulations and scenarios with hcc, as well as use it as a local proxy to capture local API traffic, or as a local reverse proxy proxying to Hoverfly Cloud. A summary of the commands is as follows:

   <pre data-full-width="true"><code>Usage:
     hcc [command]

   Available Commands:
     capture            Commands for interacting with local capture proxy
     config             Get/set CLI config properties
     help               Help about any command
     reverse-proxy      Commands for interacting with local reverse proxy proxying to Hoverfly Cloud
     scenario           Commands for interacting with Hoverfly Cloud Scenarios
     service            Commands for interacting with Hoverfly Cloud Services
     simulation         Commands for interacting with Hoverfly Cloud Simulations
     version            Get the version of Hoverfly Cloud CLI

   Flags:
         --api-token string   API token from Hoverfly Cloud
         --domain string      Domain name of Hoverfly Cloud
     -h, --help               help for hcc
         --insecure           Allow reverse proxy to private Hoverfly Cloud deployment without certs
   </code></pre>
4. `hcc` cannot control all the settings in Hoverfly Cloud however, for that you need to use the REST API directly.

## Part 3. Use the Hoverfly Cloud API to retrieve information about a service

Follow these steps:

1. Where there are functional limitations with `hcc`, all functionality available within Hoverfly Cloud can be accessed via the Hoverfly Cloud API.
2. The Hoverfly Cloud API uses hypermedia and resources include links to other related resources in their responses using the [Hypertext Application from resource to resource. Language (HAL)](http://stateless.co/hal_specification.html) format.
3. With the product service running in Hoverfly Cloud, issue the following GET request to the Hoverfly Cloud API to retrieve information about your running service:

   `https://cloud.hoverfly.io/hoverfly-cloud/api/v1/users/<<user-name>>/hoverflies/product`

   * You will need to add a bearer token containing your API key in a header called Authorization. The API key can be retrieved from your Account page in Hoverfly Cloud.
   * eg. `curl -H "Authorization: Bearer 7254a454c7123454593jgjae06a17025a7" https://cloud.hoverfly.io/hoverfly-cloud/api/v1/users/<<user-name>>/hoverflies/product`
4. You will receive a response similar to this:

   ```json
   {
       "name": "product",
       "createdBy": "user-name",
       "createdDate": "2023-06-16T15:04:45Z",
       "dnsName": "product-yourUID.hoverfly.io",
       "status": "PAUSED",
       "instanceCount": 1,
       "simulation": {
           "name": "product",
           "uuid": "d01225d16a5e44fd882243fa14449b6e",
           "versionId": "64854b1684be4acd8991db1d960f57b1"
       },
       "mode": "simulate",
       "_links": {
           "self": {
               "href": "https://cloud.hoverfly.io/hoverfly-cloud/api/v1/users/user-name/hoverflies/product"
           },
           "journal": {
               "href": "https://cloud.hoverfly.io/hoverfly-cloud/api/v1/users/user-name/hoverflies/product/journal"
           },
           "time-series": {
               "href": "https://cloud.hoverfly.io/hoverfly-cloud/api/v1/users/user-name/hoverflies/product/timeSeries"
           },
           "simulation": {
               "href": "https://cloud.hoverfly.io/hoverfly-cloud/api/v1/users/user-name/hoverflies/product/simulation"
           },
           "behavior": {
               "href": "https://cloud.hoverfly.io/hoverfly-cloud/api/v1/users/user-name/hoverflies/product/behavior"
           },
           "stats": {
               "href": "https://cloud.hoverfly.io/hoverfly-cloud/api/v1/users/user-name/hoverflies/product/stats"
           },
           "diff": {
               "href": "https://cloud.hoverfly.io/hoverfly-cloud/api/v1/users/user-name/hoverflies/product/diff"
           },
           "reset": {
               "href": "https://cloud.hoverfly.io/hoverfly-cloud/api/v1/users/user-name/hoverflies/product/data"
           }
       }
   }
   ```
5. While this gives you information about the service, it's status and the simulation it is using, it also give you links to other resources on the Hoverfly Cloud API related to the management of the product service. Let's add some behavior.

## Part 4. Adding behavior to a running service

Follow these steps:

1. If you issue a request to the link to the behavior endpoint returned by the query to the service endpoint above, you will receive an error, as there are no configured behaviors as yet for this service. We will add a 40% chance of a 404 Response code and a latency histogram behavior.
2. Issue the following PUT request with the same Authorization header as before, and with a json Request body as follows:

   ```json
   {
       "behaviors": [
           {
               "name": "randomStatusCode",
               "config": {
                   "statusCodes": {
                       "404": 0.4
                   }
               }
           },
           {
               "name": "delayByHistogram",
               "config": {
                   "latencies": [
                       100,
                       200,
                       400
                   ]
               }
           }
       ]
   }
   ```
3. If successful you should receive a response similar to the below:

   ```json
   {
       "name": "product",
       "createdBy": "your-account",
       "createdDate": "2023-08-15T13:40:03Z",
       "dnsName": "product-youUID.hoverfly.io",
       "status": "RUNNING",
       "instanceCount": 1,
       "simulation": {
           "name": "product-sim",
           "uuid": "97f93d32644d40b785187cf42563c620",
           "versionId": "49f6d6c653f54103a9c76fda3814e849"
       },
       "mode": "simulate",
       "behaviorEnabled": true,
       "_links": {
           "self": {
               "href": "https://cloud.hoverfly.io/hoverfly-cloud/api/v1/users/your-account/hoverflies/product"
           },
           "journal": {
               "href": "https://cloud.hoverfly.io/hoverfly-cloud/api/v1/users/your-account/hoverflies/product/journal"
           },
           "time-series": {
               "href": "https://cloud.hoverfly.io/hoverfly-cloud/api/v1/users/your-account/hoverflies/product/timeSeries"
           },
           "simulation": {
               "href": "https://cloud.hoverfly.io/hoverfly-cloud/api/v1/users/your-account/hoverflies/product/simulation"
           },
           "behavior": {
               "href": "https://cloud.hoverfly.io/hoverfly-cloud/api/v1/users/your-account/hoverflies/product/behavior"
           },
           "stats": {
               "href": "https://cloud.hoverfly.io/hoverfly-cloud/api/v1/users/your-account/hoverflies/product/stats"
           },
           "diff": {
               "href": "https://cloud.hoverfly.io/hoverfly-cloud/api/v1/users/your-account/hoverflies/product/diff"
           },
           "reset": {
               "href": "https://cloud.hoverfly.io/hoverfly-cloud/api/v1/users/your-account/hoverflies/product/data"
           }
       }
   }
   ```

## Part 5. Test the modified service

Follow these steps:

1. Refresh the Dashboard
2. Notice that the product service line now has a magic wand icon. This indicates that behaviors are now in play. Click it to open the behaviors dialogue.

   <figure><img src="/files/PEOVCUgxVxSGVG4p6dNF" alt=""><figcaption></figcaption></figure>
3. You will notice that the behaviors are configured as set via the API.

   <figure><img src="/files/hFf6zeqLv2qo5SzGkGHM" alt=""><figcaption></figcaption></figure>
4. Test the running service by hitting the single endpoint with your API client: `https://product-`*`youraccounthere`*`.hoverfly.io/product/12345`
5. You should receive Not Found errors 40% of the time and the latency should be noticeable.
6. Note that the API is extensive and covers all areas of functionality for Hoverfly Cloud. If it can be done through the management portal it can be done through the API.

## Part 6. Remove the service and simulation

Follow these steps:

1. Unless you want to keep the service and simulation, they can be deleted.
2. To delete the service and it's copy of the simulation navigate to the Dashboard, open the ellipse to the right of the product service that you created, and select Delete.
3. To delete the master simulation, navigate to the Simulations page, locate the simulation you created, and click the corresponding x at the right of page.

Congratulations! You have completed this Tutorial, "Using the CLI and the Hoverfly Cloud API"


