0% found this document useful (0 votes)
86 views390 pages

microsoft-cloud-dev-dev-proxy

Dev Proxy is an API simulator designed to help developers test their applications against various API failures without altering their code. It allows users to simulate API errors, rate limits, and slow responses, enhancing app robustness and user experience. The tool is open source, command-line based, and compatible with any platform, making it versatile for different tech stacks.

Uploaded by

niko19gr
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
86 views390 pages

microsoft-cloud-dev-dev-proxy

Dev Proxy is an API simulator designed to help developers test their applications against various API failures without altering their code. It allows users to simulate API errors, rate limits, and slow responses, enhancing app robustness and user experience. The tool is open source, command-line based, and compatible with any platform, making it versatile for different tech stacks.

Uploaded by

niko19gr
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 390

Tell us about your PDF experience.

What is Dev Proxy?


Article • 02/03/2025

Dev Proxy is an API simulator that helps you effortlessly test your app beyond the happy
path.

You test your app to make sure it works as intended. But what if the APIs you use fail?
Will your app lose your customer's data? How do you test for this? Simulating API
failures is hard. You end up writing code that you won't be shipping or worse: not
testing at all. That's why we built Dev Proxy, to simulate API errors so that you can easily
test your app without changing your code.

With Dev Proxy you:

See how your app responds to API errors, without changing your app’s code, so
that you can build more robust apps and don't lose customers' data.
Verify how your app handles API rate limits, so that you can avoid getting throttled
and improve the user experience for your customers.
See how your app handles slow APIs, so that you can implement the necessary
affordances, and make your app more user-friendly.
Quickly stand-up mock APIs without writing a line of code, so that you can focus
on building your app instead of writing code you won't be shipping.
Improve your app with contextual guidance on how you use APIs, to make your
app even better.

Dev Proxy is a command-line tool that works on any platform. Because it intercepts
network requests, it works with any type of app and tech stack. Dev Proxy is open source
and free to use.

How does your app handle API errors?

Get started
Set up Dev Proxy
Article • 02/07/2025

Dev Proxy is a command line tool that helps you simulate behaviors and errors of cloud
APIs to help you build resilient apps.

In this tutorial, you learn how to install and run Dev Proxy.

Install Dev Proxy


The easiest way to install Dev Proxy is by using winget. Alternatively, you can install Dev
Proxy manually.

Automated

To install Dev Proxy using winget, run the following command:

Console

winget install Microsoft.DevProxy --silent

) Important

Dev Proxy installer adds a new entry to PATH. To use Dev Proxy after
installation, you must restart the command prompt to refresh the PATH
environment variable.

7 Note

To try the latest preview features, install the beta version of Dev Proxy.

Automated

To install Dev Proxy using winget, run the following command:

Console

winget install Microsoft.DevProxy.Beta --silent


To run the beta version of Dev Proxy, use devproxy-beta

Start Dev Proxy for the first time


The first time you start Dev Proxy on your machine there are a few steps to follow to
ensure that Dev Proxy can intercept requests from your machine and respond
successfully. You won't have to repeat these steps after the first run.

1. Start Dev Proxy. Open a command prompt session. Enter devproxy and press
Enter .
2. Trust certificate. Dev Proxy installs a certificate named Dev Proxy CA . A warning
shows. Select Yes to confirm that you want to install the certificate. Dev Proxy uses
this certificate to decrypt HTTPS traffic sent from your machine.
3. Allow firewall access. Windows Firewall blocks the proxy. A warning shows. Select
Allow access button to allow traffic through the firewall.

The command prompt displays the following output:

text

info 8 error responses loaded from devproxy-errors.json


info Dev Proxy API listening on http://localhost:8897...
info Dev Proxy Listening on 127.0.0.1:8000...

Hotkeys: issue (w)eb request, (r)ecord, (s)top recording, (c)lear screen


Press CTRL+C to stop Dev Proxy

By default, Dev Proxy is configured to:

Intercept requests made to any JSON Placeholder API endpoint


Simulate API error responses and API throttling with a failure rate of 50%

Confirm that Dev Proxy is working correctly


Dev Proxy intercepts requests that applications on your machine make to URLs that you
register with Dev Proxy. When Dev Proxy detects a request, it either passes it through to
the API (take no action), or returns a response. Let's confirm that Dev Proxy is working as
expected.

In PowerShell, use the Invoke-WebRequest cmdlet to send a GET request to the JSON
Placeholder API.
PowerShell

Invoke-WebRequest -Uri https://jsonplaceholder.typicode.com/posts

If you use curl , send a GET request to the JSON Placeholder API using the following
command.

Console

curl -ikx http://localhost:8000 https://jsonplaceholder.typicode.com/posts

You can also use an API client like Postman to send a GET request to
https://jsonplaceholder.typicode.com/posts .

In the command line where Dev Proxy is running, you see the information about the
request and the action that Dev Proxy performed. By default, Dev Proxy simulates an
error response with a 50% chance. If your request doesn't return an error, Dev Proxy
passes it through.

text

req ╭ GET https://jsonplaceholder.typicode.com/posts


time │ 1/31/2025 12:12:14 PM +00:00
skip │ RetryAfterPlugin: Request not throttled
skip │ GenericRandomErrorPlugin: Pass through
api ╰ Passed through

If Dev Proxy returns an error response, you see the error message in the output.

text

req ╭ GET https://jsonplaceholder.typicode.com/posts


time │ 1/31/2025 12:12:37 PM +00:00
skip │ RetryAfterPlugin: Request not throttled
oops ╰ 403 Forbidden

) Important

If you don't see any output in the command prompt, it's likely that Dev Proxy isn't
intercepting requests. Check the common problems section for help.

Stop Dev Proxy safely


When you no longer require Dev Proxy to be running, you should always stop it safely.

Press Ctrl + C to safely stop Dev Proxy.

If you shut down the command prompt session, Dev Proxy doesn't unregister correctly
as the system proxy, and you might experience some common problems.

Next step
Learn how to configure Dev Proxy to your needs. Dev Proxy is highly flexible and
supports many different scenarios. Learn more about how to configure it to your specific
scenario.

Configure Dev Proxy


Configure Dev Proxy
Article • 02/05/2025

Dev Proxy is highly configurable. It uses plugins to implement functionality. You can
combine any of the standard plugins and build your own. By using plugins and custom
configurations, you can tailor Dev Proxy to your specific needs. Dev Proxy includes a
default configuration file, named devproxyrc.json . The file is located in Dev Proxy's
installation folder.

 Tip

We recommend that you create custom configuration files. By using custom


configuration files, you can easily switch between different configurations and can
include them in your source control system along with your project's code. Storing
your configuration with your project also makes it easier to share it with your team.

If you name your configuration file devproxyrc.json or devproxyrc.jsonc , Dev


Proxy automatically loads it from the current directory when you start it. For other
names, specify the file path in the --config-file argument when starting Dev
Proxy, for example devproxy --config-file ./my-devproxy-config.json .

Configuration file structure


The following code snippet shows the default Dev Proxy configuration file:

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/rc.schema.json",
"plugins": [
{
"name": "RetryAfterPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
},
{
"name": "GenericRandomErrorPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "genericRandomErrorPlugin"
}
],
"urlsToWatch": [
"https://jsonplaceholder.typicode.com/*"
],
"genericRandomErrorPlugin": {
"errorsFile": "devproxy-errors.json"
},
"rate": 50,
"logLevel": "information",
"newVersionNotification": "stable",
"showSkipMessages": true,
"showTimestamps": true
}

The configuration file consists of three sections:

Schema, defined in the $schema property. To ensure that your config file is valid, be
sure to use the same schema version as the Dev Proxy version you're using.
The list of plugins that Dev Proxy uses, defined in the plugins array.
General configuration settings.

) Important

Dev Proxy applies plugins in the order they're listed in the configuration file. Be
mindful of the order to get the desired behavior.

Some plugins are configurable and expose their own settings. Each plugin has its own
configuration section in the configuration file, referenced by the configSection property
in the plugin definition. See the reference documentation for each plugin to learn more
about its configuration options.

 Tip

The value of the configSection property can be any string. By using different
names, you can include multiple instances of the same plugin, each with a different
configuration. You might need to reference the same plugin multiple times, for
example, when mocking multiple APIs with different error responses and behaviors.

Dev Proxy Toolkit


Dev Proxy Toolkit is a Visual Studio Code extension that significantly simplifies
configuring Dev Proxy. Here are some of the features it includes:

code snippets for common configuration scenarios


extended linting and IntelliSense for Dev Proxy configuration files
custom editor actions and commands to conveniently start and stop Dev Proxy
notifications about new versions of Dev Proxy

 Tip

If you use Visual Studio Code, we highly recommend that you install the Dev Proxy
Toolkit extension.

Next step
If you want to keep learning about using Dev Proxy, consider the following tutorials:

Simulate random errors for your own application


Test a JavaScript client-side web application that calls Microsoft Graph
Test a JavaScript client-side web application

Otherwise, check out our how to guides to learn how to use Dev Proxy for specific
scenarios.
Simulate random errors for your own
application
Article • 04/08/2024

In this tutorial, you learn how to use Dev Proxy to simulate random errors for your own
application.

Prerequisites
This part of the tutorial assumes that you installed and configured Dev Proxy on your
machine. If not, do that now.

To follow this tutorial, you need an application that calls APIs. You also need to know the
URLs of the APIs that your application calls.

You can use Dev Proxy with any type of application and technology stack. Here are
instructions for how to set up Dev Proxy with a few popular technologies.

JavaScript

Use Dev Proxy with:

Node.js applications
Node.js applications in Docker
JavaScript Azure Functions
SharePoint Framework (SPFx) solutions

Start Dev Proxy with monitoring your URLs


Start Dev Proxy and monitor the URLs of the APIs that your application calls. For
example, if your application calls an API located at
https://api.contoso.com/v1/customers , start Dev Proxy and monitor the URL pattern

https://api.contoso.com/* .

Console

devproxy --urls-to-watch "https://api.contoso.com/*"


The --urls-to-watch parameter tells Dev Proxy, which requests to intercept. The
wildcard * at the end of the URL tells Dev Proxy to intercept all requests to URLs that
start with https://api.contoso.com/ .

Start using your application as you normally would. Dev Proxy intercepts all requests to
the URLs that you specified. In the command prompt, you see messages about the
requests that Dev Proxy intercepts.

text

```text
request GET https://api.contoso.com/v1/customers
api ╭ Passed through
╰ GET https://api.contoso.com/v1/customers
request GET https://api.contoso.com/v1/customers
chaos ╭ 403 Forbidden
╰ GET https://api.contoso.com/v1/customers

) Important

If you don't see any messages in the command prompt, make sure that you
correctly configured your application to use Dev Proxy. Also, check if Dev Proxy is
intercepting requests to API URLs that your application uses. If you have any
questions, ask for help in the Dev Proxy community on Discord.

Create your own configuration files


By default, Dev Proxy uses the devproxyrc.json file in the Dev Proxy installation folder
for its configuration settings. The file is configured to simulate random errors for the
JSON Placeholder API. To get more realistic results, create your own configuration files
with errors that are more relevant to your application and the APIs it uses, and use them
with Dev Proxy.

Let's consider that you want to store a configuration file in the project folder for your
app, so you can share the configuration settings with the rest of your team.

1. In the Dev Proxy installation folder, copy devproxyrc.json and devproxy-


errors.json .

2. In your project folder, paste the files.

When using a configuration file that is stored outside of the Dev Proxy installation file,
you need to ensure that the pluginPath references are correct. Rather than hard coding
the paths to the Dev Proxy installation folder in your configuration file, you can use the
~appFolder at the beginning of the path to include a dynamic reference back to the Dev

Proxy installation folder.

1. In a text editor, open the devproxyrc.json file.


2. Locate the GenericRandomErrorPlugin plugin in the plugins array.
3. Update the pluginPath to ~appFolder/plugins/dev-proxy-plugins.dll .
4. Locate the RetryAfterPlugin plugin in the plugins array.
5. Update the pluginPath to ~appFolder/plugins/dev-proxy-plugins.dll .
6. In a command prompt, change the working directory to your project folder.
7. Enter devproxy --config-file devproxyrc.json and press Enter to start Dev Proxy
using your configuration file.
8. Send a request to the JSON Placeholder API from the command line and view the
output.
9. Press Ctrl + C to safely stop Dev Proxy.

 Tip

Install the Dev Proxy Toolkit extension for Visual Studio Code which makes it
easy to create and update configuration files.

Next step
Dev Proxy supports many different scenarios that help you build more robust
applications. Explore the how-to guides to learn how to use the different Dev Proxy
features and improve your application.

Explore how-to guides

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
be found on GitHub, where you Select a link to provide feedback:
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
Test a JavaScript client-side web
application
Article • 04/08/2024

In this tutorial, you learn how to use Dev Proxy to test how a sample JavaScript client-
side web application handles API errors.

Prerequisites
This part of the tutorial assumes that you installed and configured Dev Proxy on your
machine. If not, do that now.

To follow this tutorial, you need:

Node.js LTS .

Download the sample app


Download the sample app .

 Tip

You can also download the sample app by running in the command prompt
devproxy preset get demo-randomerror-js .

The sample app comes with a Dev Proxy preset. The preset is configured to simulate
random errors on API requests issued by the app. The preset also includes the
RetryAfterPlugin, which helps you control if the app backs off from calling API after it's
throttled.

Start Dev Proxy and the sample app


1. In a command prompt, change the working directory to where the sample app is
located.
2. Start the sample app and Dev Proxy by running npm start

Test the sample app


1. In a web browser, navigate to http://localhost:3000

If you see an empty page, check the Console window. It could be that Dev
Proxy has already simulated an API error, which the app didn't handle!

2. Navigate through the list of articles to see how the app handles API errors that Dev
Proxy simulates.

You can find more information about the errors in the Console window and in
the command prompt where Dev Proxy is running.

3. Press Ctrl + C to stop Dev Proxy.

Next step
Explore How-to guides

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
Test a JavaScript client-side web
application that calls Microsoft Graph
Article • 02/05/2025

In this tutorial, you learn how to use Dev Proxy to test a sample JavaScript client-side
web application that calls Microsoft Graph.

Prerequisites
This part of the tutorial assumes that you installed and configured Dev Proxy on your
machine. If not, do that now.

To follow this tutorial, you need:

Microsoft 365 tenant.


Account with permissions to create Microsoft Entra app registrations.
Git (see GitHub’s set up Git guide ).
nodejs LTS .

 Tip

We recommend that you use a Microsoft 365 Developer Tenant with content packs
installed. Get your free tenant by signing up to the Microsoft 365 Developer
Program .

Clone and configure the sample app


Download the sample app
Follow the instructions to configure the app.

Start Dev Proxy


Dev Proxy comes with a preset configuration for testing apps that send requests to
Microsoft Graph and SharePoint Online APIs.

Open a command prompt, enter devproxy --config-file


"~appFolder/presets/m365.json" and press Enter to start Dev Proxy with

configuration for Microsoft 365.


Launch the sample app
Open a command prompt and change to the samples directory.
Enter npx lite-server and press Enter to start the sample app web server.

Test the sample app


1. In the running app, select the Without SDK button.

U Caution

If you got an empty page after clicking the Without SDK button, check that you
have configured the Azure AD App Registration . The issue occurs when the
.env file containing the Client ID of your app registration is missing.

1. Select the Login button and complete the sign in flow.


Dev Proxy introduces faults into your application by intercepting requests to Microsoft
Graph. It uses 50% chance for failing requests with a random supported HTTP error
status code.

View the proxy output and take a moment to refresh the sample app. See how the
sample app handles (or not, in this case) the failures introduced by the proxy.
1. Press Ctrl + C to stop Dev Proxy.

Next step
Explore How-to guides
How-to guides for Dev Proxy
Article • 04/02/2025

Get help and support

Intercept requests
Discover URLs to watch
Intercept requests from specific processes
Intercept requests with specific headers
Intercept requests to localhost
Exclude a URL
Inspect requests and responses using Chrome DevTool
Inspect API requests issued by cloud services

Mock responses
Mock responses
Mock n-th request
Mock responses that return binary data
Mock multiple responses to the same endpoint
Change mocks file
Simulate a CRUD API
Simulate a CRUD API across the internet
Simulate a CRUD API secured with Microsoft Entra
Simulate Azure OpenAI API
Simulate OpenAI API
Mock Teams Admin Center notification for Microsoft Graph connectors

Simulate errors
Test my app with random errors
Simulate errors from OpenAI APIs
Simulate errors from Microsoft Graph APIs
Change request failure rate

Simulate behaviors
Test that my application handles throttling properly
Simulate throttling on Microsoft 365 APIs
Simulate Rate-Limit API responses
Simulate slow API responses

Minimal permissions
Detect minimal Microsoft Graph API permissions
Check if you're using excessive Microsoft Graph API permissions

Record
Record and export proxy activity

Improve my app
Check if my app is using production-level APIs
Check if my app is calling APIs with minimal permissions
Find shadow APIs
Generate an OpenAPI spec
Update my application code to use Microsoft Graph JavaScript SDK

Presets
Use preset configurations

Change settings
Change logging level
Clear the output
Use local language model with Dev Proxy
Refresh local Microsoft Graph database

Use Dev Proxy


In a Docker container
With Node.js applications
With Node.js applications in Docker containers
With JavaScript Azure Functions
With .NET applications
With .NET applications in Docker containers
With .NET Aspire applications
With SharePoint Framework (SPFx) solutions
In CI/CD scenarios

Common problems
No requests are intercepted
No random errors are thrown when using mocks
No internet connection after using the proxy
All requests fail with 429 responses
All requests fail with gateway time-out
Binary responses aren't mocked
No requests are intercepted from my .NET 4.8 app
Options aren't recognized
The type initializer for 'Microsoft.Data.Sqlite.SqliteConnection' threw an exception
Uninstall
Get help and support
Discover URLs to watch
Article • 04/28/2025

Dev Proxy allows you to simulate behaviors for APIs. To do that, you need to know which URLs
your app is calling and configure Dev Proxy to intercept them.

To find out which URLs your app is calling, use the --discover option. This option loads a
preset that uses the UrlDiscoveryPlugin and PlainTextReporter to create a list of URLs that the
proxy intercepts.

The discovery preset is configured to intercept requests to any URL and pass them through to
the original API. It uses the UrlDiscoveryPlugin , to generate a list of unique URLs, and the
PlainTextReporter to save the list to a text file.

 Tip

Before you start Dev Proxy with the --discover option, find out from which process you
want to capture requests. You can specify the process by its ID or name. Without this
option, Dev Proxy intercepts all requests made by your machine, which makes it hard to
find the URLs you're interested in. For more information, see Intercept requests from
specific processes.

For example, to discover URLs that a client-side application uses, running in Microsoft Edge on
Windows, run the following command:

Console

devproxy --discover --watch-process-names msedge

After you start Dev Proxy, interact with your application so that it issues requests to the APIs
you want to simulate. Dev Proxy intercepts these requests. When you finish, stop Dev Proxy by
pressing Ctrl+C . The urls-to-watch preset saves the list of URLs to the
UrlDiscoveryPlugin_PlainTextReporter.txt file in the current directory.

Next steps
Learn more about the UrlDiscoveryPlugin.

UrlDiscoveryPlugin
Intercept requests from specific
processes
Article • 04/08/2024

By default, Dev Proxy is registered as a system wide proxy and all requests made by your
machine are passed through the proxy.

By default, the proxy intercepts requests that are made from your machine to the URLs
configured in devproxyrc.json file.

However, you might also want to only intercept requests being made from specific
processes such as a command prompt window or web browser.

To intercept request from processes by their given process IDs, use the --watch-pids
option:

Console

devproxy –-watch-pids 870 135100

To intercept request from processes by their given process names, use the --watch-
process-names option:

Console

devproxy --watch-process-names msedge pwsh

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
Intercept requests with specific headers
Article • 04/30/2025

By default, Dev Proxy intercepts all requests that match the URLs configured in the
devproxyrc.json file. When you want to intercept only specific requests, such as requests issued
by a specific component, you can configure Dev Proxy to intercept requests with specific
headers.

To intercept requests with specific headers, in the devproxyrc.json file, add the
filterByHeaders property. In the filterByHeaders property, specify the headers that you want

to use to filter the requests. For each header, specify the value that the header should contain
for Dev Proxy to intercept the request. If you leave the value empty, Dev Proxy intercepts
requests that contain the specified header, regardless of its value.

Example: Intercept requests with a specific header


and value
The following example demonstrates how to configure Dev Proxy to intercept requests that
contain the x-app header with a value that contains contoso-intranet :

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/rc.schema.json",
"plugins": [
// [...] trimmed for brevity
],
"filterByHeaders": [
{
"name": "x-app",
"value": "contoso-intranet"
}
]
}

Using this configuration, Dev Proxy intercepts requests that contain the x-app header with the
value contoso-intranet , for example:

HTTP

GET https://api.contoso.com/customers
x-app: contoso-intranet
Dev Proxy also intercepts requests that partially match the specified value, for example:

HTTP

GET https://api.contoso.com/customers
x-app: contoso-intranet-search

Dev Proxy doesn't intercept the following request because the value of the x-app header
doesn't contain contoso-intranet :

HTTP

GET https://api.contoso.com/customers
x-app: contoso-public

Partial matching is convenient and allows you to intercept requests with values that can change
over time, such as component or SDK version.

Example: Intercept requests with a specific header


no matter the value
To intercept requests that contain a specific header, regardless of its value, leave the value
empty:

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/rc.schema.json",
"plugins": [
// [...] trimmed for brevity
],
"filterByHeaders": [
{
"name": "x-contoso",
"value": ""
}
]
}

Using this configuration, Dev Proxy intercepts requests that contain the x-contoso header,
regardless of its value:

HTTP
GET https://api.contoso.com/customers
x-contoso: api-sdk v1.0

Or:

HTTP

GET https://api.contoso.com/customers
x-contoso: intranet

Dev Proxy doesn't intercept the following request because it doesn't have the x-contoso
header:

HTTP

GET https://api.contoso.com/customers
x-app: contoso-public
Intercept requests to localhost
Article • 03/20/2025

By default, Chromium-based browsers such as Microsoft Edge and Google Chrome


bypass system proxy settings for localhost URLs. If you're developing an application
that makes requests to API on localhost , which you want to intercept using Dev Proxy,
you need to exclude localhost URLs from the bypass list.

To configure Chromium-based browsers to send requests to the system proxy for


localhost URLs, you need to start the browser with the --proxy-bypass-list and --
proxy-server options. For example, to exclude localhost from the bypass list in

Microsoft Edge, start the browser with the following command:

msedge --proxy-bypass-list="<-loopback> --proxy-server="127.0.0.1:8000"

) Important

Before you start a Chromium-based browser with these settings, be sure to close all
instances of the browser. Otherwise, the new settings won't take effect.

To configure Mozilla Firefox to send requests to the system proxy for localhost URLs,
you need to set the network.proxy.allow_hijacking_localhost preference to true . To
do that, open the about:config page in Firefox, search for the
network.proxy.allow_hijacking_localhost preference, and set it to true .
Exclude a URL
Article • 04/30/2025

To exclude a URL from being intercepted, prepend it with an ! (exclamation mark):

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/rc.schema.json",
"urlsToWatch": [
"https://graph.microsoft.com/v1.0/*",
"https://graph.microsoft.com/beta/*",
"https://graph.microsoft.us/v1.0/*",
"https://graph.microsoft.us/beta/*",
"https://dod-graph.microsoft.us/v1.0/*",
"https://dod-graph.microsoft.us/beta/*",
"https://microsoftgraph.chinacloudapi.cn/v1.0/*",
"https://microsoftgraph.chinacloudapi.cn/beta/*",
"!https://*.sharepoint.*/*_api/web/GetClientSideComponents",
"https://*.sharepoint.*/*_api/*",
"https://*.sharepoint.*/*_vti_bin/*",
"https://*.sharepoint-df.*/*_api/*",
"https://*.sharepoint-df.*/*_vti_bin/*"
]
}

In the above example, the proxy ignores any requests made to


/_api/web/GetClientSideComponents .

When excluding URLs, keep in mind that proxy looks for matching URLs in the order in which
they’re defined in the configuration.

If you want to exclude specific URLs, you should define them first, before more global URL
matches.
Inspect requests and responses using
Chrome DevTools
Article • 04/30/2025

By default, Dev Proxy displays its messages in the command prompt. If you use Dev Proxy with
an application that issues many requests, it's difficult to find the messages you're interested in.
What's more, you might want to inspect the requests and responses intercepted by Dev Proxy.

To make it easier to find the messages you're interested in, use the DevToolsPlugin plugin to
display Dev Proxy messages in Chrome DevTools.

 Tip

Dev Proxy supports using Chrome DevTools with Microsoft Edge, Microsoft Edge Dev and
Google Chrome.

The DevToolsPlugin exposes Dev Proxy messages, and information about intercepted requests
and responses in Chrome DevTools.


To use Chrome DevTools with Dev Proxy:

1. Open the devproxyrc.json file stored in your Dev Proxy installation directory. You can also
use the devproxy config open command.

2. Enable the DevToolsPlugin plugin, by adding the following fragment to the plugins
array:

JSON

{
"name": "DevToolsPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "devTools"
}

3. Add the devTools section and specify your preferred browser:

JSON
"devTools": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/devtoolsplugin.schema.json",
"preferredBrowser": "Edge"
}

 Tip

Supported values are: Edge , EdgeDev , Chrome

4. The complete devproxyrc.json file looks like:

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/rc.schema.json",
"plugins": [
{
"name": "DevToolsPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "devTools"
}
],
"devTools": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/devtoolsplugin.schema.json",
"preferredBrowser": "Edge"
}
}

5. Save the devproxyrc.json file and start Dev Proxy.


Inspect API requests issued by cloud
services
Article • 04/30/2025

When you integrate your application with cloud services, one of the challenges you might face
is understanding how the cloud service interacts with the APIs it uses. Being able to inspect API
requests is especially important when you're troubleshooting issues or when you're trying to
understand how the cloud service works. Typically, it's challenging, because you don't have
access to the cloud service's runtime, and you also might not have access to the monitoring
tools for the cloud API. By using Dev Proxy and dev tunnels, you can inspect the API requests
that cloud services issue to cloud APIs.

) Important

Before you continue, install dev tunnels and configure the tool for use.

How cloud services call cloud APIs


When you integrate your application with cloud services, the cloud service calls your API in the
cloud. The following diagram illustrates this scenario:

To inspect API requests that the cloud service issues, you need access to the monitoring tools
for the cloud API. Often, you don't have access to these tools. You could work around this
limitation, by using a staging environment. However, it's time-consuming to set up and
maintain a staging environment. What's more, if you don't own the cloud API, you might not
be able to set up a staging environment at all.
Inspect API requests using Dev Proxy and dev
tunnels
By using Dev Proxy and dev tunnels, you can inspect the API requests that the cloud service
issues to the cloud API.

Rather than calling the cloud API directly, you configure the cloud service to call the dev tunnel
you run on your local machine (1). You configure dev tunnel to use a host header that Dev
Proxy intercepts. Each time the cloud service calls the dev tunnel, it passes the request to Dev
Proxy which intercepts it (2). Using the Dev Proxy RewritePlugin, you change the URL of the
intercepted request, and forward it to the cloud API (3). The cloud API processes the request
and returns a response to Dev Proxy (4). Dev Proxy passes the response to dev tunnel (5),
which forwards it to the cloud service (6). Because the request is routed through your local
machine, you can inspect its information, including URL, headers, and body, and the response
from the cloud API.

Scenario
Say you want to inspect API requests that a cloud service issues to the demo JSONPlaceholder
API located at https://jsonplaceholder.typicode.com . By combining Dev Proxy and dev
tunnels, you can intercept the requests and inspect their information.

You can inspect the requests either by using dev tunnels inspections tools, or using the Dev
Proxy DevToolsPlugin. Both tools use Chrome Dev Tools to show information about intercepted
requests and responses. When you use the dev tunnels inspections tools, you see the dev
tunnel URL as the request URL. In comparison, when you use the Dev Proxy DevToolsPlugin,
you see how Dev Proxy intercepts the request, using either the local or the rewritten URL.

Inspect API requests using Dev Proxy, dev tunnels,


and dev tunnels inspection tools
1. Configure Dev Proxy to intercept requests to https://jsonplaceholder.typicode.com and
http://jsonplaceholder.typicode.local :

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/rc.schema.json",
"plugins": [
{
"name": "RewritePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "rewritePlugin"
}
],
"urlsToWatch": [
"https://jsonplaceholder.typicode.com/*",
"http://jsonplaceholder.typicode.local/*"
],
"rewritePlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/rewriteplugin.schema.json",
"rewritesFile": "devproxy-rewrites.json"
},
"logLevel": "information",
"newVersionNotification": "stable",
"showSkipMessages": true
}

The configuration file uses the RewritePlugin to rewrite the URL of the intercepted
requests. It also configures Dev Proxy to intercept requests to
https://jsonplaceholder.typicode.com and http://jsonplaceholder.typicode.local

URLs.
7 Note

While it's not necessary to use a .local domain, it's a good practice that helps you
distinguish between the real and the intercepted requests. Also notice, that for the
.local domain, you use the HTTP protocol, rather than HTTPS. Dev tunnels doesn't

support HTTPS for routing requests to custom host headers on your local machine
which is why you need to use HTTP.

2. Create a rewrite file named devproxy-rewrites.json that changes the URL of the
intercepted requests:

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/rewriteplugin.rewritesfile.schema.json",
"rewrites": [
{
"in": {
"url": "^http://jsonplaceholder.typicode.local(.*)"
},
"out": {
"url": "https://jsonplaceholder.typicode.com$1"
}
}
]
}

The rewrite file changes the URL of the intercepted requests from
http://jsonplaceholder.typicode.local to https://jsonplaceholder.typicode.com .

3. Start Dev Proxy by running in the command line devproxy .


4. Start dev tunnel by running in the command line devtunnel host --host-header
jsonplaceholder.typicode.local --port-numbers 8000 --allow-anonymous .

Using this command, you open a new dev tunnel on your machine. You map it to the
8000 port which is where Dev Proxy listens for incoming requests. You also specify the
host header that Dev Proxy intercepts.

5. Note the URL of the dev tunnel that you can use to configure the cloud service to call
your local machine, for example https://tunnel_id-8000.euw.devtunnels.ms .
6. In a web browser, open the dev tunnel inspection URL, for example https://tunnel_id-
8000-inspect.euw.devtunnels.ms .

7. Simulate a cloud service calling the cloud API by using the dev tunnel URL, by running in
the command line: curl https://tunnel_id-8000.euw.devtunnels.ms/posts/1 .

7 Note

Notice, that the host name corresponds to the URL of the dev tunnel on your
machine. The path matches the path of the API you want to inspect.

8. Notice how Dev Proxy intercepts the request, and forwards it to the cloud API, eventually
returning the response to the client.

9. In the web browser, notice the information about the intercepted request and the
response from the cloud API.

7 Note

Notice that the recorded request URL is the URL of the dev tunnel. The recorded
host header is the host header that Dev Proxy intercepts.

10. Close the dev tunnel and stop Dev Proxy by pressing Ctrl + C in their respective sessions
in the command line.

Inspect API requests using Dev Proxy and


DevToolsPlugin
Another way to inspect the API requests that the cloud service issues, is by using the Dev Proxy
DevToolsPlugin. The difference between using the DevToolsPlugin and the dev tunnels
inspection tools is that the DevToolsPlugin shows how Dev Proxy intercepts the request, using
either the local or the rewritten URL.

Configure Dev Proxy to use the DevToolsPlugin to inspect API


requests using the intercepted URL
First, let's configure Dev Proxy to inspect cloud API requests. Let's configure the DevToolsPlugin
to show the information about the URL before Dev Proxy rewrites it.

1. Update the Dev Proxy configuration file to use the DevToolsPlugin:

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/rc.schema.json",
"plugins": [
{
"name": "DevToolsPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
},
{
"name": "RewritePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "rewritePlugin"
}
],
"urlsToWatch": [
"https://jsonplaceholder.typicode.com/*",
"http://jsonplaceholder.typicode.local/*"
],
"rewritePlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/rewriteplugin.schema.json",
"rewritesFile": "devproxy-rewrites.json"
},
"logLevel": "information",
"newVersionNotification": "stable",
"showSkipMessages": true
}

7 Note
Notice, that we add the DevToolsPlugin before the RewritePlugin. By adding the
DevToolsPlugin first, it shows the information about the intercepted request before
it's rewritten.

2. Start Dev Proxy by running in the command line devproxy . Notice that Dev Proxy opens a
web browser window with Chrome Dev Tools visible.

3. Start dev tunnel by running in the command line devtunnel host --host-header
jsonplaceholder.typicode.local --port-numbers 8000 --allow-anonymous .

4. Simulate a cloud service calling the cloud API by using the dev tunnel URL, by running in
the command line: curl https://tunnel_id-8000.euw.devtunnels.ms/posts/1 .

5. In the web browser with Chrome Dev Tools, notice the information about the intercepted
request and the response from the cloud API.

7 Note

Notice that the recorded request URL is the URL of the cloud API. The recorded host
header is the host header that Dev Proxy intercepts.

6. Close the dev tunnel and stop Dev Proxy by pressing Ctrl + C in their respective sessions
in the command line.

Configure Dev Proxy to use the DevToolsPlugin to inspect API


requests using the rewritten URL
Next, let's update Dev Proxy configuration to show the information about the rewritten URL.

1. Update the Dev Proxy configuration file by moving the DevToolsPlugin after the
RewritePlugin:

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/rc.schema.json",
"plugins": [
{
"name": "RewritePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "rewritePlugin"
},
{
"name": "DevToolsPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
}
],
"urlsToWatch": [
"https://jsonplaceholder.typicode.com/*",
"http://jsonplaceholder.typicode.local/*"
],
"rewritePlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/rewriteplugin.schema.json",
"rewritesFile": "devproxy-rewrites.json"
},
"logLevel": "information",
"newVersionNotification": "stable",
"showSkipMessages": true
}

2. Start Dev Proxy by running in the command line devproxy . Notice that Dev Proxy opens a
web browser window with Chrome Dev Tools visible.

3. Start dev tunnel by running in the command line devtunnel host --host-header
jsonplaceholder.typicode.local --port-numbers 8000 --allow-anonymous .

4. Simulate a cloud service calling the cloud API by using the dev tunnel URL, by running in
the command line: curl https://tunnel_id-8000.euw.devtunnels.ms/posts/1 .

5. In the web browser with Chrome Dev Tools, notice the information about the intercepted
request and the response from the cloud API.

7 Note

Notice that both the recorded request URL, and the host header show the URL of the
cloud API.

6. Close the dev tunnel and stop Dev Proxy by pressing Ctrl + C in their respective sessions
in the command line.

Summary
By using Dev Proxy and dev tunnels, you can inspect the API requests that cloud services issue
to cloud APIs. You can use either dev tunnels inspection tools, or the Dev Proxy DevToolsPlugin
to inspect the requests. Both tools show you the information about the intercepted requests,
including the URL, headers and body, and the response from the cloud API. By using Dev Proxy
and dev tunnels, you can better understand how cloud services interact with cloud APIs, and
troubleshoot issues more effectively.

Next steps
Learn more about the RewritePlugin.

RewritePlugin
Mock responses
Article • 04/30/2025

Using Dev Proxy is the easiest way to mock an API. Whether you're building the front-end and
the API isn't ready yet, you need to integrate your back-end with an external service, or you
want to test your application with different responses, Dev Proxy can help you simulate API
responses. What's great about using Dev Proxy is that it doesn't require any changes to your
application code. You define mock responses for any API that your application interacts with
and Dev Proxy intercepts the requests and responds with the mock responses that you defined.

To mock API responses, you need to do two things:

1. Create a file with mock responses.


2. Configure Dev Proxy to use the mock responses.

 Tip

If you use Visual Studio Code, consider installing the Dev Proxy Toolkit extension. It
significantly simplifies working with Dev Proxy configuration files.

Create a file with mock responses


Dev Proxy mocks API responses using the MockResponsePlugin. The plugin allows you to
define a set of mock responses. You define the mocks in a separate file. The following code
snippet demonstrates a simple mock response for a GET request to
https://jsonplaceholder.typicode.com/posts/1 .

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/mockresponseplugin.mocksfile.schema.json",
"mocks": [
{
"request": {
"url": "https://jsonplaceholder.typicode.com/posts/1",
"method": "GET"
},
"response": {
"statusCode": 200,
"body": {
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio
reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et
cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem
eveniet architecto"
},
"headers": [
{
"name": "Date",
"value": "Wed, 19 Feb 2025 09:03:37 GMT"
},
{
"name": "Content-Type",
"value": "application/json; charset=utf-8"
},
{
"name": "Content-Length",
"value": "292"
},
// [...] trimmed for brevity
]
}
}
]
}

 Tip

Instead of creating the mocks file manually, you can use the MockGeneratorPlugin to
generate the mocks file based on the intercepted requests.

Order precedence
Dev Proxy matches mocks in the order in which you define them in the mocks file. If you define
multiple responses with the same URL and method, Dev Proxy uses the first matching
response.

When you use the following configuration, proxy responds to all GET requests to
https://graph.microsoft.com/v1.0/me/photo with 500 Internal Server Error .

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/mockresponseplugin.mocksfile.schema.json",
"mocks": [
{
"request": {
"url": "https://graph.microsoft.com/v1.0/me/photo",
"method": "GET"
},
"response": {
"statusCode": 500
}
},
{
"request": {
"url": "https://graph.microsoft.com/v1.0/me/photo",
"method": "GET"
},
"response": {
"statusCode": 404
}
}
]
}

Wildcard support
Dev Proxy supports the use of wildcards in the URL property. You can use the asterisk character
( * ) to match any series of characters in the URL.

When you use the following configuration, Dev Proxy responds to all requests to get any user's
profile with the same response.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/mockresponseplugin.mocksfile.schema.json",
"mocks": [
{
"request": {
"url": "https://graph.microsoft.com/v1.0/users/*"
},
"response": {
"body": {
"@odata.context":
"https://graph.microsoft.com/v1.0/$metadata#users/$entity",
"businessPhones": ["+1 425 555 0109"],
"displayName": "Adele Vance",
"givenName": "Adele",
"jobTitle": "Product Marketing Manager",
"mail": "[email protected]",
"mobilePhone": null,
"officeLocation": "18/2111",
"preferredLanguage": "en-US",
"surname": "Vance",
"userPrincipalName": "[email protected]",
"id": "87d349ed-44d7-43e1-9a83-5f2406dee5bd"
}
}
}
]
}

When you use the following configuration, Dev Proxy returns the same image from disk when
you request to get the binary of any user's photo.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/mockresponseplugin.mocksfile.schema.json",
"mocks": [
{
"request": {
"url": "https://graph.microsoft.com/v1.0/users/*/photo/$value"
},
"response": {
"body": "@picture.jpg",
"headers": [
{
"name": "content-type",
"value": "image/jpeg"
}
]
}
}
]
}

When you use the following configuration, Dev Proxy returns the same response when you
request to get the current user's profile with any query string parameter.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/mockresponseplugin.mocksfile.schema.json",
"mocks": [
{
"request": {
"url": "https://graph.microsoft.com/v1.0/me?*"
},
"response": {
"body": {
"@odata.context":
"https://graph.microsoft.com/v1.0/$metadata#users/$entity",
"businessPhones": [
"+1 412 555 0109"
],
"displayName": "Megan Bowen",
"givenName": "Megan",
"jobTitle": "Auditor",
"mail": "[email protected]",
"mobilePhone": null,
"officeLocation": "12/1110",
"preferredLanguage": "en-US",
"surname": "Bowen",
"userPrincipalName": "[email protected]",
"id": "48d31887-5fad-4d73-a9f5-3c356e68a038"
}
}
}
]
}

Respond with contents of a file


To keep your mocks file clean and organized, you can store the contents of the response in a
separate file and reference it in the mocks file. To instruct Dev Proxy, to load the mock
response body from a file, set the body property to @ followed by the file path relative to the
mocks file.

For example, the following mock response configuration, instructs Dev Proxy to respond to any
request to https://graph.microsoft.com/v1.0/me with the contents of the response.json file
located in the same folder as the mocks file.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/mockresponseplugin.mocksfile.schema.json",
"mocks": [
{
"request": {
"url": "https://graph.microsoft.com/v1.0/me",
"method": "GET"
},
"response": {
"body": "@response.json",
"headers": [
{
"name": "content-type",
"value": "application/json; odata.metadata=minimal"
}
]
}
}
]
}

Using the @ -token works with text and binary files.

Configure Dev Proxy to use the mock responses


After you create the mocks file, you need to configure Dev Proxy to use the mock responses. To
configure Dev Proxy to mock responses, add the MockResponsePlugin to the list of plugins in
the devproxyrc file.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/rc.schema.json",
"plugins": [
{
"name": "MockResponsePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "mockResponsePlugin"
}
],
"urlsToWatch": [
"https://jsonplaceholder.typicode.com/*"
],
"mockResponsePlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/mockresponseplugin.schema.json",
"mocksFile": "mocks.json"
},
"logLevel": "information",
"newVersionNotification": "stable",
"showSkipMessages": true
}

First, you add the MockResponsePlugin to the list of plugins. You include a reference to its
configuration section where you specify the path to your mocks file.

When you start Dev Proxy, it reads the mocks file and uses the mock responses to respond to
the requests that match the defined mocks.

Unmocked request support


Dev Proxy supports throwing an error when proxy intercepts an unmocked request. The ability
to fail unmocked requests is useful for identifying requests that you missed in your mocks file.

To enable this feature, add and enable the blockUnmockedRequests setting to


MockResponsePlugin config section in the devproxyrc file.

JSON

{
"mocksPlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/mockresponseplugin.schema.json",
"mocksFile": "mocks.json",
"blockUnmockedRequests": true
}
}

When Dev Proxy intercepts a request which it can't mock, it returns a 502 Bad Gateway
response.

Next step
Learn more about the MockResponsePlugin.

MockResponsePlugin

Samples
See also the related Dev Proxy samples:

Microsoft Graph mocks from Microsoft Graph API docs


Microsoft Graph mocks from Microsoft Graph API docs with sandbox data
Simulate creating a Microsoft Graph connector and its schema
Mock nth request
Article • 02/05/2025

Dev Proxy supports mocking n-th through the nth property on the request object.

 Tip

Download this preset by running in the command prompt devproxy preset get
microsoft-graph-connector .

Using the following mock file as an example, we can see that it contains two mocks to
the same request URL. Proxy uses the first response that uses the nth property, when it
intercepts a request with the specified URL for the second time. For all other requests,
the proxy returns the second response.

 Tip

Mocks with the nth property should be first. Proxy uses mocks based on the first
match.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/mockresponseplugin.schema.json",
"mocks": [
{
"request": {
"url":
"https://graph.microsoft.com/v1.0/external/connections/*/operations/*",
"method": "GET",
"nth": 2
},
"response": {
"statusCode": 200,
"body": {
"id":
"1.neu.0278337E599FC8DBF5607ED12CF463E4.6410CCF8F6DB8758539FB58EB56BF8DC",
"status": "completed",
"error": null
}
}
},
{
"request": {
"url":
"https://graph.microsoft.com/v1.0/external/connections/*/operations/*",
"method": "GET"
},
"response": {
"statusCode": 200,
"body": {
"id":
"1.neu.0278337E599FC8DBF5607ED12CF463E4.6410CCF8F6DB8758539FB58EB56BF8DC",
"status": "inprogress",
"error": null
}
}
}
]
}

Next step
Learn more about the MockResponsePlugin.

MockResponsePlugin

Samples
See also the related Dev Proxy samples:

Simulate creating a Microsoft Graph connector and its schema


Mock responses that return binary data
Article • 02/05/2025

For some requests, you might want to respond with binary data like documents or
images.

In Dev Proxy, you can define a binary response by setting the response.body to a string
value that starts with @ followed by file path relative to the current working directory,
for example:

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/mockresponseplugin.schema.json",
"mocks": [
{
"request": {
"url": "https://graph.microsoft.com/v1.0/users/*/photo/$value",
"method": "GET"
},
"response": {
"body": "@picture.jpg",
"headers": [
{
"name": "content-type",
"value": "image/jpeg"
}
]
}
}
]
}

When you call GET


https://graph.microsoft.com/v1.0/users/[email protected]/photo/$value , you get the

image stored in the picture.jpg file in the current directory.

U Caution

If you're using the command line to execute the HTTP request, ensure that you
have correctly escaped the dollar sign. See Why is proxy not mocking my binary
response.
Next step
Learn more about the MockResponsePlugin.

MockResponsePlugin

Samples
See also the related Dev Proxy samples:

Simulate errors on Microsoft Graph with HTTP Cats


Mock multiple responses to the same
endpoint
Article • 02/05/2025

When defining mock responses, you can define a specific URL to mock, but also a URL
pattern by replacing part of the URL with an * (asterisk), for example:

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/mockresponseplugin.schema.json",
"mocks": [
{
"request": {
"url": "https://graph.microsoft.com/v1.0/users/*",
"method": "GET"
},
"response": {
"body": {
"@odata.context":
"https://graph.microsoft.com/v1.0/$metadata#users/$entity",
"businessPhones": [
"+1 425 555 0109"
],
"displayName": "Adele Vance",
"givenName": "Adele",
"jobTitle": "Product Marketing Manager",
"mail": "[email protected]",
"mobilePhone": null,
"officeLocation": "18/2111",
"preferredLanguage": "en-US",
"surname": "Vance",
"userPrincipalName": "[email protected]",
"id": "87d349ed-44d7-43e1-9a83-5f2406dee5bd"
}
}
}
]
}

would respond to GET requests for


https://graph.microsoft.com/v1.0/users/[email protected] and
https://graph.microsoft.com/v1.0/users/[email protected] with the same mock

response.
If a URL of a mock response contains an * , the proxy considers it a regular expression,
where each * is converted into a .* , basically matching any sequence of characters.
Expanding wildcards is important to keep in mind, because if a pattern is too broad and
defined before more specific mocks, it could unintentionally return unexpected
responses, for example:

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/mockresponseplugin.schema.json",
"mocks": [
{
"request": {
"url": "https://graph.microsoft.com/v1.0/users/*",
"method": "GET"
},
"response": {
"body": {
"@odata.context":
"https://graph.microsoft.com/v1.0/$metadata#users/$entity",
"businessPhones": [
"+1 425 555 0109"
],
"displayName": "Adele Vance",
"givenName": "Adele",
"jobTitle": "Product Marketing Manager",
"mail": "[email protected]",
"mobilePhone": null,
"officeLocation": "18/2111",
"preferredLanguage": "en-US",
"surname": "Vance",
"userPrincipalName": "[email protected]",
"id": "87d349ed-44d7-43e1-9a83-5f2406dee5bd"
}
}
},
{
"request": {
"url": "https://graph.microsoft.com/v1.0/users/48d31887-5fad-4d73-
a9f5-3c356e68a038",
"method": "GET"
},
"response": {
"body": {
"@odata.context":
"https://graph.microsoft.com/v1.0/$metadata#users/$entity",
"businessPhones": [
"+1 412 555 0109"
],
"displayName": "Megan Bowen",
"givenName": "Megan",
"jobTitle": "Auditor",
"mail": "[email protected]",
"mobilePhone": null,
"officeLocation": "12/1110",
"preferredLanguage": "en-US",
"surname": "Bowen",
"userPrincipalName": "[email protected]",
"id": "48d31887-5fad-4d73-a9f5-3c356e68a038"
}
}
}
]
}

for request GET https://graph.microsoft.com/v1.0/users/48d31887-5fad-4d73-a9f5-


3c356e68a038 , the proxy would return Adele Vance instead of Megan Bowen , because the

asterisk at the end matches any series of characters. The correct way to define these
responses, would be to change their order in the array:

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/mockresponseplugin.schema.json",
"mocks": [
{
"request": {
"url": "https://graph.microsoft.com/v1.0/users/48d31887-5fad-4d73-
a9f5-3c356e68a038",
"method": "GET"
},
"response": {
"body": {
"@odata.context":
"https://graph.microsoft.com/v1.0/$metadata#users/$entity",
"businessPhones": [
"+1 412 555 0109"
],
"displayName": "Megan Bowen",
"givenName": "Megan",
"jobTitle": "Auditor",
"mail": "[email protected]",
"mobilePhone": null,
"officeLocation": "12/1110",
"preferredLanguage": "en-US",
"surname": "Bowen",
"userPrincipalName": "[email protected]",
"id": "48d31887-5fad-4d73-a9f5-3c356e68a038"
}
}
},
{
"request": {
"url": "https://graph.microsoft.com/v1.0/users/*",
"method": "GET"
},
"response": {
"body": {
"@odata.context":
"https://graph.microsoft.com/v1.0/$metadata#users/$entity",
"businessPhones": [
"+1 425 555 0109"
],
"displayName": "Adele Vance",
"givenName": "Adele",
"jobTitle": "Product Marketing Manager",
"mail": "[email protected]",
"mobilePhone": null,
"officeLocation": "18/2111",
"preferredLanguage": "en-US",
"surname": "Vance",
"userPrincipalName": "[email protected]",
"id": "87d349ed-44d7-43e1-9a83-5f2406dee5bd"
}
}
}
]
}

 Tip

As a rule of thumb, define the mocks with the longest (most specific) URLs first. Put
mocks with shorter URLs and URLs with wildcards (less specific) towards the end of
the array.
Change mocks file
Article • 04/08/2024

By default, the MockResponsePlugin and GraphMockResponsePlugin Dev Proxy plugins


looks for a file called mocks.json in the current working directory.

To use a file with a different name, use:

Console

devproxy --mocks-file my-mocks.json

Alternatively, you can specify the mocks file in the devproxyrc.json configuration file.

JSON

{
"mocksPlugin": {
"mocksFile": "mocks.json"
}
}

Learn more about the MockResponsePlugin .

MockResponsePlugin

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
Simulate a CRUD API
Article • 02/05/2025

When building apps, you often interact with backend APIs. Sometimes, these APIs aren't
yet available, or other teams are updating them to meet the latest requirements. To
avoid waiting, you typically create a mock API that returns the data you need. While this
approach unblocks you, it requires you to spend time on building an API that you
eventually replace with the real one. To avoid wasting time, you can use Dev Proxy to
simulate a CRUD API and speed up development.

Using the CrudApiPlugin, you can simulate a CRUD (Create, Read, Update, Delete) API
with an in-memory data store. Using a simple configuration file, you can define which
URLs your mock API supports and what data it returns. The plugin also supports CORS
for cross-domain usage from client-side applications.

Where the MockResponsePlugin allows you to define static mock responses, the
CrudApiPlugin allows you to define a dynamic mock API that you can use to interact

with data and see your changes reflected in the mock data set.

Scenario
Say, you're building an app that allows users to manage customers. To get the data, you
need to call the /customers endpoint of the backend API. To avoid waiting for the
backend team to finish their work, you decide to use Dev Proxy to simulate the API and
return the data you need.

You start with enabling the CrudApiPlugin and configuring it to use the customers-
api.json file.

JSON

{
"name": "CrudApiPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "customersApi"
}

JSON

{
"customersApi": {
"apiFile": "customers-api.json"
}
}

In the customers-api.json file, you define the mock customers API.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/crudapiplugin.schema.json",
"baseUrl": "https://api.contoso.com/v1/customers",
"dataFile": "customers-data.json",
"actions": [
{
"action": "getAll"
},
{
"action": "getOne",
"url": "/{customer-id}",
"query": "$.[?(@.id == {customer-id})]"
},
{
"action": "create"
},
{
"action": "merge",
"url": "/{customer-id}",
"query": "$.[?(@.id == {customer-id})]"
},
{
"action": "delete",
"url": "/{customer-id}",
"query": "$.[?(@.id == {customer-id})]"
}
]
}

In the baseUrl property, you define the base URL of the mock API. In the dataFile
property, you define the file that contains mock customer data. In the actions property,
you define the supported actions and how they map to the HTTP methods and URLs.
You want to use your API to:

get all customers, by calling GET /v1/customers


get a single customer, by calling GET /v1/customers/{customer-id}
add a new customer, by calling POST /v1/customers ,
update a customer, by calling PATCH /v1/customers/{customer-id} ,
delete a customer, by calling DELETE /v1/customers/{customer-id}
In your URLs, you use the {customer-id} parameter, which the plugin replaces with the
actual customer ID from the URL. The plugin also uses the {customer-id} parameter in a
JSONPath query to look up the customer in the data file.

In the customers-data.json file, you define the mock customer data.

JSON

[
{
"id": 1,
"name": "Contoso",
"address": "4567 Main St Buffalo, NY 98052"
},
{
"id": 2,
"name": "Fabrikam",
"address": "4567 Main St Buffalo, NY 98052"
}
]

You start Dev Proxy and call the https://api.contoso.com/v1/customers endpoint. Dev
Proxy intercepts the request and returns the mock customer data.

JSON

[
{
"id": 1,
"name": "Contoso",
"address": "4567 Main St Buffalo, NY 98052"
},
{
"id": 2,
"name": "Fabrikam",
"address": "4567 Main St Buffalo, NY 98052"
}
]

Next step
Learn more about the CrudApiPlugin.

CrudApiPlugin

Samples
See also the related Dev Proxy samples:

CRUD APIs with Northwind database data


Simulate a CRUD API across the internet
Article • 02/05/2025

Dev Proxy allows you to simulate CRUD APIs without having to build them. Simulating
APIs using Dev Proxy allows you to save time and speed up development. When you
integrate your API with cloud services, you need to expose your API across the internet
so that the cloud service can access it. To expose a CRUD API simulated by Dev Proxy
across the internet, use Dev Tunnels. This article explains how to configure a CRUD API
to be exposed across the internet using Dev Tunnels.

 Tip

The CRUD API in this article is based on the Northwind database Dev Proxy
sample .

Configure CRUD API to be exposed across the


internet
To expose a CRUD API simulated by Dev Proxy across the internet, start by configuring
the CRUD API.

) Important

At this moment, you can only expose HTTP CRUD APIs across the internet using
Dev Tunnels.

Define the CRUD API data


Create a data file, named orders-data.json , that backs the CRUD API, for example:

JSON

[
{
"OrderID": 10248,
"CustomerID": "VINET",
"EmployeeID": 5,
"OrderDate": "1996-07-04T00:00:00",
"RequiredDate": "1996-08-01T00:00:00",
"ShippedDate": "1996-07-16T00:00:00",
"ShipVia": 3,
"Freight": 32.38,
"ShipName": "Vins et alcools Chevalier",
"ShipAddress": "59 rue de l'Abbaye",
"ShipCity": "Reims",
"ShipPostalCode": "51100",
"ShipCountry": "France"
},
{
"OrderID": 10249,
"CustomerID": "TOMSP",
"EmployeeID": 6,
"OrderDate": "1996-07-05T00:00:00",
"RequiredDate": "1996-08-16T00:00:00",
"ShippedDate": "1996-07-10T00:00:00",
"ShipVia": 1,
"Freight": 11.61,
"ShipName": "Toms Spezialitäten",
"ShipAddress": "Luisenstr. 48",
"ShipCity": "Münster",
"ShipPostalCode": "44087",
"ShipCountry": "Germany"
}
]

Configure the CRUD API


Next, create the API configuration file named orders-api.json , where you specify the
CRUD API URL, its operations, and data file. Be sure to specify an HTTP URL in the
baseUrl property:

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/crudapiplugin.schema.json",
"baseUrl": "http://api.northwind.com/orders",
"auth": "none",
"dataFile": "orders-data.json",
"actions": [
{
"action": "getAll"
},
{
"action": "getOne",
"url": "/{order-id}",
"query": "$.[?(@.OrderID == {order-id})]"
},
{
"action": "create"
},
{
"action": "merge",
"url": "/{order-id}",
"query": "$.[?(@.OrderID == {order-id})]"
},
{
"action": "delete",
"url": "/{order-id}",
"query": "$.[?(@.OrderID == {order-id})]"
}
]
}

Define Dev Proxy configuration


Next, create a Dev Proxy configuration file named devproxyrc.json with the
CrudApiPlugin enabled. Configure Dev Proxy to listen to the URL that you configured

for your CRUD API:

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/rc.schema.json",
"plugins": [
{
"name": "CrudApiPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "ordersApi"
}
],
"urlsToWatch": [
"http://api.northwind.com/*"
],
"ordersApi": {
"apiFile": "orders-api.json"
}
}

Verify configuration
Verify that the CRUD API is working correctly by running Dev Proxy and sending
requests to the CRUD API.

Start Dev Proxy, assuming you saved the Dev Proxy configuration in a file named
devproxyrc.json in the current working directory:
Console

devproxy

Call the CRUD API using curl:

Console

$ curl -x http://127.0.0.1:8000 http://api.northwind.com/orders

[
{
"OrderID": 10248,
"CustomerID": "VINET",
"EmployeeID": 5,
"OrderDate": "1996-07-04T00:00:00",
"RequiredDate": "1996-08-01T00:00:00",
"ShippedDate": "1996-07-16T00:00:00",
"ShipVia": 3,
"Freight": 32.38,
"ShipName": "Vins et alcools Chevalier",
"ShipAddress": "59 rue de l'Abbaye",
"ShipCity": "Reims",
"ShipPostalCode": "51100",
"ShipCountry": "France"
},
{
"OrderID": 10249,
"CustomerID": "TOMSP",
"EmployeeID": 6,
"OrderDate": "1996-07-05T00:00:00",
"RequiredDate": "1996-08-16T00:00:00",
"ShippedDate": "1996-07-10T00:00:00",
"ShipVia": 1,
"Freight": 11.61,
"ShipName": "Toms Spezialitäten",
"ShipAddress": "Luisenstr. 48",
"ShipCity": "Münster",
"ShipPostalCode": "44087",
"ShipCountry": "Germany"
}
]

Expose the CRUD API across the internet


To expose the CRUD API across the internet, start a dev tunnel mapped to the Dev Proxy
port. Configure the tunnel to use the host name configured for the CRUD API.

2 Warning
Allowing anonymous access to a dev tunnel means anyone on the internet is able
to connect to your local server, if they can guess the dev tunnel ID.

Console

$ devtunnel host -p 8000 -a --host-header api.northwind.com

Hosting port: 8000


Connect via browser: https://vpfm55qw.euw.devtunnels.ms:8000,
https://vpfm55qw-8000.euw.devtunnels.ms
Inspect network activity: https://vpfm55qw-8000-inspect.euw.devtunnels.ms

Ready to accept connections for tunnel: vpfm55qw

Call the CRUD API that Dev Proxy simulates via dev tunnel using curl:

Console

$ curl https://vpfm55qw-8000.euw.devtunnels.ms/orders

[
{
"OrderID": 10248,
"CustomerID": "VINET",
"EmployeeID": 5,
"OrderDate": "1996-07-04T00:00:00",
"RequiredDate": "1996-08-01T00:00:00",
"ShippedDate": "1996-07-16T00:00:00",
"ShipVia": 3,
"Freight": 32.38,
"ShipName": "Vins et alcools Chevalier",
"ShipAddress": "59 rue de l'Abbaye",
"ShipCity": "Reims",
"ShipPostalCode": "51100",
"ShipCountry": "France"
},
{
"OrderID": 10249,
"CustomerID": "TOMSP",
"EmployeeID": 6,
"OrderDate": "1996-07-05T00:00:00",
"RequiredDate": "1996-08-16T00:00:00",
"ShippedDate": "1996-07-10T00:00:00",
"ShipVia": 1,
"Freight": 11.61,
"ShipName": "Toms Spezialitäten",
"ShipAddress": "Luisenstr. 48",
"ShipCity": "Münster",
"ShipPostalCode": "44087",
"ShipCountry": "Germany"
}
]
Simulate a CRUD API secured with
Microsoft Entra
Article • 02/05/2025

When building apps, you often interact with backend APIs. Sometimes, these APIs aren't
yet available, or other teams are updating them to meet the latest requirements. To
avoid waiting, you typically create a mock API that returns the data you need. While this
approach unblocks you, it requires you to spend time on building an API that you
eventually replace with the real one. It gets even more complicated, when you need to
secure your API with Microsoft Entra. To avoid wasting time, you can use Dev Proxy to
simulate a CRUD API and speed up development.

Using the CrudApiPlugin, you can simulate a CRUD (Create, Read, Update, Delete) API
with an in-memory data store. Using a simple configuration file, you can define which
URLs your mock API supports and what data it returns. The plugin also supports CORS
for cross-domain usage from client-side applications. The plugin also supports Microsoft
Entra authentication, so you can secure your mock API with Microsoft Entra and
implement the same authentication flow for your app as in your production
environment.

Scenario
Say, you're building an app that allows users to manage customers. To get the data, you
need to call the /customers endpoint of the backend API. The API is secured with
Microsoft Entra. To avoid waiting for the backend team to finish their work, you decide
to use Dev Proxy to simulate the API and return the data you need.

Before you begin


You start by creating a simulated CRUD API with customer data. After confirming that
the API works, you can secure it with Microsoft Entra.

Example 1: Simulate a CRUD API secured with


Microsoft Entra using a single scope
In the first example, you secure the whole API with a single scope. No matter if users
need to get information about customers or update them, they use the same
permission.
In the customers-api.json file, add information about Entra.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/crudapiplugin.schema.json",
"baseUrl": "https://api.contoso.com/v1/customers",
"dataFile": "customers-data.json",
"auth": "entra",
"entraAuthConfig": {
"audience": "https://api.contoso.com",
"issuer": "https://login.microsoftonline.com/contoso.com",
"scopes": ["api://contoso.com/user_impersonation"]
},
"actions": [
{
"action": "getAll"
},
{
"action": "getOne",
"url": "/{customer-id}",
"query": "$.[?(@.id == {customer-id})]"
},
{
"action": "create"
},
{
"action": "merge",
"url": "/{customer-id}",
"query": "$.[?(@.id == {customer-id})]"
},
{
"action": "delete",
"url": "/{customer-id}",
"query": "$.[?(@.id == {customer-id})]"
}
]
}

By setting the auth property to entra you specify, that the API is secured with Microsoft
Entra. In the entraAuthConfig property, you specify the configuration details. The
audience property specifies the audience of the API, the issuer property specifies the

issuer of the tokens, and the scopes property specifies the scopes required to access the
API. Because you define scopes at the root level of the API file, all actions require the
same scope.

If you try to call the API without a token with the specified audience, issuer, and scopes,
you get a 401 Unauthorized response.
7 Note

At this stage, Dev Proxy doesn't validate the token. It only checks if the token is
present and has the required audience, issuer, and scopes. This is convenient
during early development, when you don't have a real Microsoft Entra app
registration yet and can't get a real token.

Example 2: Simulate a CRUD API secured with


Microsoft Entra using different scopes for
different actions
In many cases, different API operations require different permissions. For example,
getting information about customers might require a different permission than updating
them. In this example, you secure different API actions with different scopes.

Update the customers-api.json file as follows:

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/crudapiplugin.schema.json",
"baseUrl": "https://api.contoso.com/v1/customers",
"dataFile": "customers-data.json",
"auth": "entra",
"entraAuthConfig": {
"audience": "https://api.contoso.com",
"issuer": "https://login.microsoftonline.com/contoso.com"
},
"actions": [
{
"action": "getAll",
"auth": "entra",
"entraAuthConfig": {
"scopes": ["api://contoso.com/customer.read"]
}
},
{
"action": "getOne",
"url": "/{customer-id}",
"query": "$.[?(@.id == {customer-id})]",
"auth": "entra",
"entraAuthConfig": {
"scopes": ["api://contoso.com/customer.read"]
}
},
{
"action": "create",
"auth": "entra",
"entraAuthConfig": {
"scopes": ["api://contoso.com/customer.write"]
}
},
{
"action": "merge",
"url": "/{customer-id}",
"query": "$.[?(@.id == {customer-id})]",
"auth": "entra",
"entraAuthConfig": {
"scopes": ["api://contoso.com/customer.write"]
}
},
{
"action": "delete",
"url": "/{customer-id}",
"query": "$.[?(@.id == {customer-id})]",
"auth": "entra",
"entraAuthConfig": {
"scopes": ["api://contoso.com/customer.write"]
}
}
]
}

This time, you don't specify the scopes at the root level of the API file. Instead, you
specify them for each action. This way, you can secure different actions with different
scopes. For example, getting information about customers requires the
api://contoso.com/customer.read scope, while updating customers requires the

api://contoso.com/customer.write scope.

Validate tokens
Dev Proxy allows you to simulate a CRUD API secured with Microsoft Entra, and check
that you're using a valid token. Validating token is convenient when you have an app
registration in Microsoft Entra, but the team is still building the API. It allows you to
more accurately test your app.

If you want Dev Proxy to validate the access token, to the entraAuthConfig property add
the validateSigningKey property and set it to true :

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/crudapiplugin.schema.json",
"baseUrl": "https://api.contoso.com/v1/customers",
"dataFile": "customers-data.json",
"auth": "entra",
"entraAuthConfig": {
"audience": "https://api.contoso.com",
"issuer": "https://login.microsoftonline.com/contoso.com",
"scopes": ["api://contoso.com/user_impersonation"],
"validateSigningKey": true
},
"actions": [
{
"action": "getAll"
},
{
"action": "getOne",
"url": "/{customer-id}",
"query": "$.[?(@.id == {customer-id})]"
},
{
"action": "create"
},
{
"action": "merge",
"url": "/{customer-id}",
"query": "$.[?(@.id == {customer-id})]"
},
{
"action": "delete",
"url": "/{customer-id}",
"query": "$.[?(@.id == {customer-id})]"
}
]
}

If you try to call the API with a self-crafted token, you get a 401 Unauthorized response.
Dev Proxy allows only requests with a valid token issued by Microsoft Entra.

Next step
Learn more about the CrudApiPlugin.

CrudApiPlugin

Samples
See also the related Dev Proxy samples:

CRUD APIs with Northwind database data


Simulate Azure OpenAI API
Article • 04/15/2025

When you build apps connected to Azure OpenAI, often, only a portion of the app interacts
with the Azure OpenAI API. When you work on the portions of the app that don't require real
replies from Azure OpenAI API, you can simulate the responses using Dev Proxy. Using
simulated responses allows you to avoid incurring unnecessary costs. The
OpenAIMockResponsePlugin uses a local language model running on your machine to simulate

responses from Azure OpenAI API.

Before you start


To simulate Azure OpenAI API responses using Dev Proxy, you need a supported language
model client installed on your machine.

By default, Dev Proxy uses the llama3.2 language model running on Ollama. To use a different
client or model, update the language model settings in the Dev Proxy configuration file.

Configure Dev Proxy to simulate Azure OpenAI API


responses

 Tip

Steps described in this tutorial are available in a ready-to-use Dev Proxy preset. To use the
preset, in command line, run devproxy preset get simulate-azure-openai , and follow the
instructions.

To simulate Azure OpenAI API responses using Dev Proxy, you need to enable the
OpenAIMockResponsePlugin in the devproxyrc.json file.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/rc.schema.json",
"plugins": [
{
"name": "OpenAIMockResponsePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
}
]
}

Next, configure Dev Proxy to intercept requests to Azure OpenAI API. For simplicity, use
wildcards to intercept requests to all deployments.

JSON

{
// [...] trimmed for brevity
"urlsToWatch": [
"https://*.openai.azure.com/openai/deployments/*/completions*"
]
}

Finally, configure Dev Proxy to use a local language model.

JSON

{
// [...] trimmed for brevity
"languageModel": {
"enabled": true
}
}

The complete configuration file looks like this.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/rc.schema.json",
"plugins": [
{
"name": "OpenAIMockResponsePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
}
],
"urlsToWatch": [
"https://*.openai.azure.com/openai/deployments/*/completions*"
],
"languageModel": {
"enabled": true
}
}
Simulate Azure OpenAI API responses
Assuming the default configuration, start Ollama with the llama3.2 language model. In the
command line, run ollama run llama3.2 .

Next, start Dev Proxy. If you use the preset, run devproxy -c "~appFolder/presets/simulate-
azure-openai/simulate-azure-openai.json . If you use a custom configuration file named

devproxyrc.json , stored in the current working directory, run devproxy . Dev Proxy checks that
it can access the language model on Ollama and confirms that it's ready to simulate Azure
OpenAI API responses.

text

info OpenAIMockResponsePlugin: Checking language model availability...


info Listening on 127.0.0.1:8000...

Hotkeys: issue (w)eb request, (r)ecord, (s)top recording, (c)lear screen


Press CTRL+C to stop Dev Proxy

Run your application and make requests to the Azure OpenAI API. Dev Proxy intercepts the
requests and simulates responses using the local language model.

Next step
Learn more about the OpenAIMockResponsePlugin.

OpenAIMockResponsePlugin

Samples
See also the related Dev Proxy samples:

Simulate Azure OpenAI API


Simulate OpenAI API
Article • 04/15/2025

When you build apps connected to OpenAI, often, only a portion of the app interacts with the
OpenAI API. When you work on the portions of the app that don't require real replies from
OpenAI API, you can simulate the responses using Dev Proxy. Using simulated responses allows
you to avoid incurring unnecessary costs. The OpenAIMockResponsePlugin uses a local language
model to simulate responses from OpenAI API.

Before you start


To simulate OpenAI API responses using Dev Proxy, you need a supported language model
client installed on your machine.

By default, Dev Proxy uses the llama3.2 language model running on Ollama. To use a different
client or model, update the language model settings in the Dev Proxy configuration file.

Configure Dev Proxy to simulate OpenAI API


responses

 Tip

Steps described in this tutorial are available in a ready-to-use Dev Proxy preset. To use the
preset, in command line, run devproxy preset get simulate-openai , and follow the
instructions.

To simulate OpenAI API responses using Dev Proxy, you need to enable the
OpenAIMockResponsePlugin in the devproxyrc.json file.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/rc.schema.json",
"plugins": [
{
"name": "OpenAIMockResponsePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
}
]
}
Next, configure Dev Proxy to intercept requests to OpenAI API. OpenAI recommends using the
https://api.openai.com/v1/chat/completions endpoint, which allows you to benefit from the

latest models and features.

JSON

{
// [...] trimmed for brevity
"urlsToWatch": [
"https://api.openai.com/v1/chat/completions"
]
}

Finally, configure Dev Proxy to use a local language model.

JSON

{
// [...] trimmed for brevity
"languageModel": {
"enabled": true
}
}

The complete configuration file looks like this.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/rc.schema.json",
"plugins": [
{
"name": "OpenAIMockResponsePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
}
],
"urlsToWatch": [
"https://api.openai.com/v1/chat/completions"
],
"languageModel": {
"enabled": true
}
}

Simulate OpenAI API responses


Assuming the default configuration, start Ollama with the llama3.2 language model. In the
command line, run ollama run llama3.2 .

Next, start Dev Proxy. If you use the preset, run devproxy -c "~appFolder/presets/simulate-
openai/simulate-openai.json . If you use a custom configuration file named devproxyrc.json ,

stored in the current working directory, run devproxy . Dev Proxy checks that it can access the
language model on Ollama and confirms that it's ready to simulate OpenAI API responses.

text

info OpenAIMockResponsePlugin: Checking language model availability...


info Listening on 127.0.0.1:8000...

Hotkeys: issue (w)eb request, (r)ecord, (s)top recording, (c)lear screen


Press CTRL+C to stop Dev Proxy

Run your application and make requests to the OpenAI API. Dev Proxy intercepts the requests
and simulates responses using the local language model.

Next step
Learn more about the OpenAIMockResponsePlugin.

OpenAIMockResponsePlugin
Samples
See also the related Dev Proxy samples:

Simulate OpenAI API


Mock Teams Admin Center notification
for Microsoft Graph connectors
Article • 02/05/2025

Microsoft Graph connectors allow you to bring your organizational content to Microsoft
365. Using Microsoft Graph connectors you're able to find your content from one place,
no matter where you store it. What's more, it gives Microsoft Copilot for Microsoft 365
access to the content, so that it can help you get more relevant answers.

When deploying Graph connectors in your organization, you should consider packaging
them as Microsoft Teams app. That way, they're deployed to the Teams Admin Center,
from which admins can control them in a familiar way. To package a Graph connector as
a Teams app, you need to extend it with an API that receives the webhook from Teams
Admin Center.

Dev Proxy allows you to test how your Microsoft Graph connector handles notifications
from the Teams Admin Center. You can mock the notification for enabling and disabling
the Graph connector and check if your connector processes it correctly. Using Dev
Proxy, you can validate configuring your connector end to end: from validating the
token, to running the initial content ingestion. Dev Proxy allows you to test your
connector locally without deploying it to the Teams Admin Center.

Before you begin


Before you start mocking Teams Admin Center notifications, complete the following
steps.

Download the Teams Admin Center notifications for


Microsoft Graph connectors Dev Proxy preset
Start, by downloading the Dev Proxy preset for simulating Teams Admin Center
notifications for Microsoft Graph connectors. In the command prompt, run the following
command:

Console

devproxy preset get microsoft-graph-connector-notification


Dev Proxy downloads the preset and saves it in the presets folder in your Dev Proxy
installation directory.

Configure the preset to send the notification to your API


In a code editor, open the ~appFolder/presets/microsoft-graph-connector-
notification/graph-connector-notification-enabled.json file, where ~appFolder refers

to the Dev Proxy installation folder. Update the request.url property with the URL of
your API that receives the notification from the Teams Admin Center.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/mockrequestplugin.schema.json",
"request": {
"url": "http://localhost:3000/api/notification",
"method": "POST",
// [...] trimmed for brevity
}
}

Follow the same steps for the graph-connector-notification-disabled.json file.

Configure tenant ID and Entra app for your Microsoft


Graph connector
Dev Proxy simulates validating the token from the Teams Admin Center notification and
issuing an access token for Microsoft Graph for your connector. Dev Proxy uses a
simulated Microsoft 365 tenant ID and an Entra app. To intercept requests from your
Graph connector, update the tenant ID to fa15d692-e9c7-4460-a743-29f29522229 and
Entra app ID to 00001111-aaaa-2222-bbbb-3333cccc4444 . If you want to use your own IDs,
update the values in all preset files.

Mock the Teams Admin Center notification for


enabling the Microsoft Graph connector
Start your API that receives the notification from the Teams Admin Center. Ensure, that it
proxies its requests through Dev Proxy.

Next, in a command prompt, start Dev Proxy with the preset for simulating the Teams
Admin Center notification for enabling the Microsoft Graph connector.
Console

devproxy --config-file "~appFolder/presets/microsoft-graph-connector-


notification/devproxyrc.json"

After Dev Proxy starts, press w to simulate the webhook from the Teams Admin Center
for enabling the Microsoft Graph connector. Dev Proxy sends the notification to your
API, which should process it as if it came from the Teams Admin Center.

When ready, to stop Dev Proxy, press Ctrl + c .

Mock the Teams Admin Center notification for


disabling the Microsoft Graph connector
In a code editor, open the ~appFolder/presets/microsoft-graph-connector-
notification/devproxyrc.json file, where ~appFolder refers to the Dev Proxy installation

folder. Locate the instance of the GraphConnectorNotificationPlugin for the enabled


notification, and change the enabled property to false . Locate the instance of the
GraphConnectorNotificationPlugin for the disabled notification, and change the enabled

property to true . The config file should be similar to:

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/rc.schema.json",
"plugins": [
{
"name": "GraphConnectorGuidancePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
},
{
"name": "GraphConnectorNotificationPlugin",
"enabled": false,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "graphConnectorNotificationEnabled"
},
{
"name": "GraphConnectorNotificationPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "graphConnectorNotificationDisabled"
},
// [...] trimmed for brevity
]
// [...] trimmed for brevity
}

Save your changes.

Follow the same steps as described previously when testing the notification for enabling
the Microsoft Graph connector.

When ready, to stop Dev Proxy, press Ctrl + c .

Next step
Learn more about the GraphConnectorNotificationPlugin.

GraphConnectorNotificationPlugin

More information
Microsoft Graph connectors overview
Enable the simplified admin experience for your Microsoft Graph connector in the
Teams admin center
Test my app with random errors
Article • 02/05/2025

When building apps, you should test how your app handles API errors. Dev Proxy allows
you to simulate errors on any API that you use in your app using the
GenericRandomErrorPlugin.

Simulate errors on any API


To start, enable the GenericRandomErrorPlugin in your configuration file.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/rc.schema.json",
"plugins": [
{
"name": "GenericRandomErrorPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "errorsContosoApi",
"urlsToWatch": [
"https://api.contoso.com/*"
]
}
]
}

 Tip

Because each API is different, you typically configure an instance of the


GenericRandomErrorPlugin for each API you want to simulate errors on. To make it

easier to manage the configuration, name the configSection after the API you
want to simulate errors on. Additionally, specify the URLs that you want to simulate
errors on in the urlsToWatch property with the plugin. This will make it easier to
manage the configuration and reuse it in the future.

Next, configure the plugin to use a file that contains the errors you want to simulate.

JSON
{
"errorsContosoApi": {
"errorsFile": "errors-contoso-api.json"
}
}

Finally, in the errors file, define the list of error responses that you want to simulate. For
example, to simulate a 500 error with a custom JSON response, use the following
configuration:

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/genericrandomerrorplugin.schema.json",
"errors": [
{
"request": {
"url": "https://api.contoso.com/*"
},
"responses": [
{
"statusCode": 500,
"headers": [
{
"name": "content-type",
"value": "application/json; charset=utf-8"
}
],
"body": {
"code": "InternalServerError",
"message": "Something went wrong"
}
}
]
}
]
}

You can define as many error responses as you need.

Start Dev Proxy with your configuration file and use your app to see how it handles the
errors. For each matching request, Dev Proxy determines whether to simulate an error or
pass the request through to the original API using the configured failure rate. When Dev
Proxy simulates an error, it uses a random error from the array of error responses you
defined in the configuration file.
Temporarily disable mocks
If you use mocks in your configuration file, you can temporarily disable them by using
the --no-mocks option.

Console

devproxy --no-mocks

Next step
Learn more about the GenericRandomErrorPlugin .

GenericRandomErrorPlugin
Simulate errors from OpenAI APIs
Article • 02/05/2025

When you use OpenAI APIs in your app, you should test how your app handles API
errors. Dev Proxy allows you to simulate errors on any OpenAI API using the
GenericRandomErrorPlugin.

 Tip

Download this preset by running in the command prompt devproxy preset get
openai-throttling .

In the Dev Proxy install folder, locate the presets folder. In the presets folder, create a
new file named openai-errors.json . Open the file in a code editor.

Create a new object in the plugins array referencing the GenericRandomErrorPlugin .


Define the OpenAI API URL for the plugin to watch for and add a reference to the plugin
configuration.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/rc.schema.json",
"plugins": [
{
"name": "GenericRandomErrorPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "openAIAPI",
"urlsToWatch": [
"https://api.openai.com/*"
]
}
]
}

Create the plugin configuration object to provide the plugin with the location of the
error responses.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.23.0/rc.schema.json",
"plugins": [
{
"name": "GenericRandomErrorPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "openAIAPI",
"urlsToWatch": [
"https://api.openai.com/*"
]
}
],
"openAIAPI": {
"errorsFile": "errors-openai.json"
}
}

In the same folder, create the errors-openai.json file. This file contains the possible
error responses that can be returned when the plugin sends an error response.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.23.0/genericrandomerrorplugin.schema.json",
"errors": [
{
"request": {
"url": "https://api.openai.com/*"
},
"responses": [
{
"statusCode": 429,
"headers": [
{
"name": "content-type",
"value": "application/json; charset=utf-8"
}
],
"body": {
"error": {
"message": "Rate limit reached for default-text-davinci-003 in
organization org-K7hT684bLccDbBRnySOoK9f2 on tokens per min. Limit:
150000.000000 / min. Current: 160000.000000 / min. Contact
[email protected] if you continue to have issues. Please add a payment
method to your account to increase your rate limit. Visit
https://beta.openai.com/account/billing to add a payment method.",
"type": "tokens",
"param": null,
"code": null
}
}
},
{
"statusCode": 429,
"headers": [
{
"name": "content-type",
"value": "application/json; charset=utf-8"
}
],
"body": {
"error": {
"message": "Rate limit reached for default-text-davinci-003 in
organization org-K7hT684bLccDbBRnySOoK9f2 on requests per min. Limit:
60.000000 / min. Current: 70.000000 / min. Contact [email protected] if you
continue to have issues. Please add a payment method to your account to
increase your rate limit. Visit https://beta.openai.com/account/billing to
add a payment method.",
"type": "requests",
"param": null,
"code": null
}
}
},
{
"statusCode": 429,
"addDynamicRetryAfter": true,
"headers": [
{
"name": "content-type",
"value": "application/json; charset=utf-8"
}
],
"body": {
"error": {
"message": "The engine is currently overloaded, please try
again later.",
"type": "requests",
"param": null,
"code": null
}
}
}
]
}
]
}

Start Dev Proxy with the configuration file:

Console

devproxy --config-file "~appFolder/presets/openai-errors.json"


When you use your app calling OpenAI APIs, Dev Proxy randomly returns one of the
error responses you defined in the errors-openai.json file.

Learn more about the GenericRandomErrorPlugin.

GenericRandomErrorPlugin
Simulate errors from Microsoft Graph
APIs
Article • 02/05/2025

Microsoft Graph is a collection of APIs that give you access to data and insights on
Microsoft 365. When you use Microsoft Graph in your app, you should test how your
app handles API errors. Dev Proxy allows you to simulate errors on any Microsoft Graph
API using the GraphRandomErrorPlugin.

The GraphRandomErrorPlugin is optimized to work with Microsoft Graph and simulates


the specific errors that Microsoft Graph can return.

To start, enable the GraphRandomErrorPlugin in your configuration file.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/rc.schema.json",
"plugins": [
{
"name": "GraphRandomErrorPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "graphRandomErrorPlugin",
"urlsToWatch": [
"https://graph.microsoft.com/v1.0/*",
"https://graph.microsoft.com/beta/*",
"https://graph.microsoft.us/v1.0/*",
"https://graph.microsoft.us/beta/*",
"https://dod-graph.microsoft.us/v1.0/*",
"https://dod-graph.microsoft.us/beta/*",
"https://microsoftgraph.chinacloudapi.cn/v1.0/*",
"https://microsoftgraph.chinacloudapi.cn/beta/*"
]
}
]
}

 Tip

The above snippet listens for requests to Microsoft Graph in all Microsoft clouds. If
you only want to simulate errors in a specific Microsoft cloud, remove the URLs that
you don't need.
Start Dev Proxy with your configuration file and use your app to see how it handles the
errors. For each matching request, Dev Proxy determines whether to simulate an error or
pass the request through to Microsoft Graph using the configured failure rate. When
Dev Proxy simulates an error, it randomly selects one of the errors that Microsoft Graph
uses, and returns an error response to your app.

Configure errors to simulate


By default, the GraphRandomErrorPlugin simulates the following errors.

ノ Expand table

HTTP Possible errors


method

GET 429 Too Many Requests , 500 Internal Server Error , 502 Bad Gateway , 503 Service
Unavailable , 504 Gateway Timeout

POST 429 Too Many Requests , 500 Internal Server Error , 502 Bad Gateway , 503 Service
Unavailable , 504 Gateway Timeout , 507 Insufficient Storage

PUT 429 Too Many Requests , 500 Internal Server Error , 502 Bad Gateway , 503 Service
Unavailable , 504 Gateway Timeout , 507 Insufficient Storage

PATCH 429 Too Many Requests , 500 Internal Server Error , 502 Bad Gateway , 503 Service
Unavailable , 504 Gateway Timeout

DELETE 429 Too Many Requests , 500 Internal Server Error , 502 Bad Gateway , 503 Service
Unavailable , 504 Gateway Timeout , 507 Insufficient Storage

If you want to test specific behaviors, such as throttling, configure the plugin to only use
the relevant errors using the --allowed-errors option.

Console

devproxy --allowed-errors 429

Alternatively, you can configure the allowedErrors property in the


graphRandomErrorPlugin object in your configuration file.

JSON

{
"graphRandomErrorPlugin": {
"allowedErrors": [ 429 ]
}
}

Simulate errors in Microsoft Graph batch


requests
Dev Proxy simulates errors in batch requests to Microsoft Graph in the same way as it
does for regular requests. When Dev Proxy fails one or more requests in a batch request,
it returns a 424 Failed Dependency response for the whole batch request, just like
Microsoft Graph would.
Change request failure rate
Article • 02/05/2025

By default, there's 50% chance that Dev Proxy returns a random error for your API. You
can change the likelihood to a different value using the --failure-rate option, for
example:

Console

devproxy --failure-rate 80

Alternatively, you can configure the failure rate in the Dev Proxy configuration file.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.14.1/rc.schema.json",
"rate": 80
}

) Important

When you configure the failure rate to 0, Dev Proxy will pass all requests through to
the original API. When you configure it to 100, Dev Proxy will simulate an error for
every matching request.
Test that my application handles
throttling properly
Article • 02/05/2025

Testing throttling is difficult because it occurs rarely, only when the server hosting the
API is under heavy load. Using the Dev Proxy, you can simulate throttling on any API,
and check if your application handles it correctly.

To simulate throttling on any API, use the GenericRandomErrorPlugin. If the API that you
use, returns a Retry-After header, use the RetryAfterPlugin to verify that your app
backs-off as instructed by the API.

Simulate throttling on any API


To start, enable the GenericRandomErrorPlugin in your Dev Proxy configuration file.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/rc.schema.json",
"plugins": [
{
"name": "GenericRandomErrorPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "errorsContosoApi",
"urlsToWatch": [
"https://api.contoso.com/*"
]
}
]
}

Next, configure the plugin to use a file that contains the errors you want to simulate.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/rc.schema.json",
"plugins": [
{
"name": "GenericRandomErrorPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "errorsContosoApi",
"urlsToWatch": [
"https://api.contoso.com/*"
]
}
],
"errorsContosoApi": {
"errorsFile": "errors-contoso-api.json"
}
}

In the errors file, define the throttling response so that it matches the actual throttling
response of your API:

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/genericrandomerrorplugin.schema.json",
"errors": [
{
"request": {
"url": "https://api.contoso.com/*"
},
"responses": [
{
"statusCode": 429,
"headers": [
{
"name": "Content-Type",
"value": "application/json"
}
],
"body": {
"code": "TooManyRequests",
"message": "Too many requests"
}
}
]
}
]
}

Start Dev Proxy with your configuration file and test your app to see how it handles
throttling.

Test correct backing off with the Retry-After


header
Many APIs use the Retry-After response header to instruct the app to back-off for a
specific amount of time. When simulating throttling responses using Dev Proxy, you can
either configure the Retry-After header to a static value, or use a dynamic value that
tests if your app is waiting as instructed before calling the API again.

To configure the Retry-After header to a static value, add the header to your throttling
response:

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/genericrandomerrorplugin.schema.json",
"errors": [
{
"request": {
"url": "https://api.contoso.com/*"
},
"responses": [
{
"statusCode": 429,
"headers": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Retry-After",
"value": "60"
}
],
"body": {
"code": "TooManyRequests",
"message": "Too many requests"
}
}
]
}
]
}

In this example, the Retry-After header is set to 60 seconds. When you configure the
header to a static value, Dev Proxy isn't controlling if your app is waiting before calling
the API again.

To test if your app is correctly waiting before calling the API again, change the header's
value to @dynamic :

JSON
{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/genericrandomerrorplugin.schema.json",
"errors": [
{
"request": {
"url": "https://api.contoso.com/*"
},
"responses": [
{
"statusCode": 429,
"headers": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Retry-After",
"value": "@dynamic"
}
],
"body": {
"code": "TooManyRequests",
"message": "Too many requests"
}
}
]
}
]
}

Additionally, extend your Dev Proxy configuration with the RetryAfterPlugin.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/rc.schema.json",
"plugins": [
{
"name": "RetryAfterPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"urlsToWatch": [
"https://api.contoso.com/*"
]
},
{
"name": "GenericRandomErrorPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "errorsContosoApi",
"urlsToWatch": [
"https://api.contoso.com/*"
]
}
],
"errorsContosoApi": {
"errorsFile": "errors-contoso-api.json"
}
}

U Caution

Add the RetryAfterPlugin before the GenericRandomErrorPlugin in your


configuration file. If you add it after, the request will be failed by the
GenericRandomErrorPlugin before the RetryAfterPlugin has a chance to handle it.

This plugin keeps track of throttling responses and forcefully fails requests issued to
APIs that are still throttled.

More information
What is throttling?
How to handle API throttling
Simulate throttling on Microsoft 365
APIs
Article • 02/05/2025

Typically, testing throttling is hard because it occurs rarely, when Microsoft 365 servers
are under heavy load. Using the Dev Proxy, you can simulate throttling responses, and
check if your application handles it correctly.

To simulate throttling on Microsoft 365 APIs, use the GraphRandomErrorPlugin and the
RetryAfterPlugin. The GraphRandomErrorPlugin returns throttling responses for Microsoft
365 APIs. The RetryAfterPlugin verifies that your app backs-off as instructed by the API.

To start, enable the GraphRandomErrorPlugin and RetryAfterPlugin in your Dev Proxy


configuration file.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/rc.schema.json",
"plugins": [
{
"name": "RetryAfterPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
},
{
"name": "GraphRandomErrorPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "graphRandomErrorPlugin"
}
],
"urlsToWatch": [
"https://graph.microsoft.com/v1.0/*",
"https://graph.microsoft.com/beta/*",
"https://graph.microsoft.us/v1.0/*",
"https://graph.microsoft.us/beta/*",
"https://dod-graph.microsoft.us/v1.0/*",
"https://dod-graph.microsoft.us/beta/*",
"https://microsoftgraph.chinacloudapi.cn/v1.0/*",
"https://microsoftgraph.chinacloudapi.cn/beta/*",
"!https://*.sharepoint.*/*_api/web/GetClientSideComponents",
"https://*.sharepoint.*/*_api/*",
"https://*.sharepoint.*/*_vti_bin/*",
"https://*.sharepoint-df.*/*_api/*",
"https://*.sharepoint-df.*/*_vti_bin/*"
]
}

U Caution

Add the RetryAfterPlugin before the GraphRandomErrorPlugin in your


configuration file. If you add it after, the request will be failed by the
GraphRandomErrorPlugin before the RetryAfterPlugin has a chance to handle it.

Next, configure the GraphRandomErrorPlugin to simulate throttling errors.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/rc.schema.json",
"plugins": [
{
"name": "RetryAfterPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
},
{
"name": "GraphRandomErrorPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "graphRandomErrorPlugin"
}
],
"urlsToWatch": [
"https://graph.microsoft.com/v1.0/*",
"https://graph.microsoft.com/beta/*",
"https://graph.microsoft.us/v1.0/*",
"https://graph.microsoft.us/beta/*",
"https://dod-graph.microsoft.us/v1.0/*",
"https://dod-graph.microsoft.us/beta/*",
"https://microsoftgraph.chinacloudapi.cn/v1.0/*",
"https://microsoftgraph.chinacloudapi.cn/beta/*",
"!https://*.sharepoint.*/*_api/web/GetClientSideComponents",
"https://*.sharepoint.*/*_api/*",
"https://*.sharepoint.*/*_vti_bin/*",
"https://*.sharepoint-df.*/*_api/*",
"https://*.sharepoint-df.*/*_vti_bin/*"
],
"graphRandomErrorPlugin": {
"allowedErrors": [ 429 ]
}
}
Start Dev Proxy with your configuration file and test your app to see how it handles
throttling.

If your application backs-off when throttled, but doesn't wait for the amount of time
specified on the requests, you see a message similar to Calling
https://graph.microsoft.com/v1.0/endpoint again before waiting for the Retry-After

period. Request will be throttled .

This message indicates that your application isn't handling throttling correctly and
unnecessarily prolongs throttling. To improve how your app handles throttling, update
your code to wait for the amount of time specified in the Retry-After header before
retrying the request.
Simulate Rate-Limit API responses
Article • 01/25/2024

Rate-Limit headers are used in HTTP responses to limit the number of requests that a
client can make within a given time period.

The server sends these headers in response to a client's request to indicate how many
requests are allowed and how many requests remain before the limit is reached.

The RateLimit-Limit response header field indicates the request-quota associated with
the client in the current time-window. If the client exceeds that limit, it might not be
served.

Custom rate limit support


When you exceed rate limit, some APIs use custom behaviors, such as returning a 403
Forbidden status code with a custom error message. Dev Proxy allows you to simulate

these custom behaviors by using the Custom value for the whenLimitExceeded property.

The following example shows how you can configure how you can configure
RateLimitingPlugin in the devproxyrc file to simulate rate limits for the GitHub API .

JSON

{
"rateLimiting": {
"headerLimit": "X-RateLimit-Limit",
"headerRemaining": "X-RateLimit-Remaining",
"headerReset": "X-RateLimit-Reset",
"costPerRequest": 1,
"resetTimeWindowSeconds": 3600,
"warningThresholdPercent": 0,
"rateLimit": 60,
"resetFormat": "UtcEpochSeconds",
"whenLimitExceeded": "Custom",
"customResponseFile": "github-rate-limit-exceeded.json"
}
}

The customResponseFile contains the response that the proxy returns when your app
reached the rate limit.

JSON
{
"statusCode": 403,
"headers": [
{
"name": "Content-Type",
"value": "application/json; charset=utf-8"
}
],
"body": {
"message": "You have exceeded a secondary rate limit and have been
temporarily blocked from content creation. Please retry your request again
later.",
"documentation_url": "https://docs.github.com/rest/overview/resources-
in-the-rest-api#secondary-rate-limits"
}
}

Next steps
Learn more about the RateLimitingPlugin .

RateLimitingPlugin

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
Simulate slow API responses
Article • 02/05/2025

Dev Proxy allows you to simulate slow API responses by using the LatencyPlugin.

Start, by enabling the plugin in your Dev Proxy configuration file:

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/rc.schema.json",
"plugins": [
{
"name": "LatencyPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "latencyPlugin"
}
],
"urlsToWatch": []
}

Next, specify the minimum and maximum delay (in milliseconds) to simulate for your
API.

JSON

"latencyPlugin": {
"minMs": 200,
"maxMs": 10000
}

When a response is delayed, Dev Proxy displays the total duration it was delayed for in
the console output.
How to check if my app is calling APIs
with minimal permissions
Article • 02/05/2025

When building your app, you likely integrate with several APIs and operations. To ensure
that your app is secure and follows the principle of least privilege, you should check if
your app is calling APIs with minimal permissions. By using minimal permissions, you
reduce the risk of unauthorized access to your data and resources.

What's hard about checking if your app is calling APIs with minimal permissions is that
each time you integrate a new operation, you need to evaluate the set of permissions
you use in your app. Manually tracking all operations and permissions is time-
consuming and error-prone. Using Dev Proxy and Azure API Center you can automate
checking if your app is calling APIs with minimal permissions.

To check if your app is calling APIs using minimal permissions, you can use the
ApiCenterMinimalPermissionsPlugin plugin. This plugin compares the permissions that
your app uses with the permissions defined in Azure API Center and reports on any
excessive permissions. It also recommends the minimal set of permissions that you
should use.

https://www.youtube-nocookie.com/embed/fFr3tFBp1Z8

Before you start


To check if your app is calling APIs using minimal permissions, you need to have an
Azure API Center instance with information about the APIs that you use in your
organization.

 Tip

Download the preset for this how to article by running in the command prompt
devproxy preset get demo-apicenter-minimalpermissions .

Create an Azure API Center instance


Before you start, create an Azure API Center instance and register APIs that you use in
your organization. For each API, upload the OpenAPI specification file that describes the
API operations and permissions.

The ApiCenterMinimalPermissionsPlugin uses this information to check if your app is


calling APIs using minimal permissions.

Copy API Center information


From the Azure API Center instance Overview page, copy the name of the API Center
instance, the name of the resource group and the subscription ID. You need this
information to configure the ApiCenterMinimalPermissionsPlugin so that it can connect
to your Azure API Center instance.

Configure Dev Proxy


To check if your app is calling APIs using minimal permissions, you need to enable the
ApiCenterMinimalPermissionsPlugin in the Dev Proxy configuration file. To create a

report of permissions that your app uses, add a reporter.

Enable the ApiCenterMinimalPermissionsPlugin


In the devproxyrc.json file, add the following configuration:

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/rc.schema.json",
"plugins": [
{
"name": "ApiCenterMinimalPermissionsPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "apiCenterMinimalPermissionsPlugin"
}
],
"urlsToWatch": [
"https://api.northwind.com/*"
],
"apiCenterMinimalPermissionsPlugin": {
"subscriptionId": "aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e",
"resourceGroupName": "demo",
"serviceName": "contoso-api-center",
"workspaceName": "default"
}
}

In the subscriptionId , resourceGroupName , and serviceName properties, provide the


information about your Azure API Center instance.

In the urlsToWatch property, specify the URLs that your app uses.

 Tip

Use the Dev Proxy Toolkit Visual Studio Code extension to easily manage Dev
Proxy configuration.

Add a reporter
The ApiCenterMinimalPermissionsPlugin produces a report of APIs that your app is
using, and the minimal permissions required to call them. To view this report, add a
reporter to your Dev Proxy configuration file. Dev Proxy offers several reporters. In this
example, you use the plain-text reporter.

Update your devproxyrc.json file with a reference to the plain-text reporter:

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/rc.schema.json",
"plugins": [
{
"name": "ApiCenterMinimalPermissionsPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "apiCenterMinimalPermissionsPlugin"
},
{
"name": "PlainTextReporter",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
}
],
"urlsToWatch": [
"https://api.northwind.com/*"
],
"apiCenterMinimalPermissionsPlugin": {
"subscriptionId": "aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e",
"resourceGroupName": "demo",
"serviceName": "contoso-api-center",
"workspaceName": "default"
}
}

Check if your app is calling APIs using minimal


permissions
To check if your app is calling APIs using minimal permissions, you need to connect to
your Azure subscription, run Dev Proxy, and let it intercept API requests from your app.
Dev Proxy then compares the information about the API requests with the information
from Azure API Center and reports on the minimal permissions.

Connect to your Azure subscription


Dev Proxy uses information from Azure API Center to determine if your app is calling
APIs using minimal permissions. To get this information, it needs a connection to your
Azure subscription. You can connect to your Azure subscription in several ways.

Run Dev Proxy


After connecting to your Azure subscription, start Dev Proxy. If you start Dev Proxy from
the same folder where your devproxyrc.json file is located, it automatically loads the
configuration. Otherwise, specify the path to the configuration file using the --config-
file option.

When Dev Proxy starts, it checks that it can connect to your Azure subscription. When
the connection is successful, you see a message similar to:

text
info Plugin ApiCenterMinimalPermissionsPlugin connecting to Azure...
info Listening on 127.0.0.1:8000...

Hotkeys: issue (w)eb request, (r)ecord, (s)top recording, (c)lear screen


Press CTRL+C to stop Dev Proxy

Press r to start recording API requests from your app.

Use your app


Use your app as you would normally do. In this tutorial, you can use the following
request with a simulated access token with customer.readwrite permission:

HTTP

@readwriteToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODk
wIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJzY3AiOlsiY3VzdG9tZXIucmV
hZHdyaXRlIl19.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

GET https://api.northwind.com/customers/ALFKI
Authorization: Bearer {{readwriteToken}}

Dev Proxy intercepts the API requests and stores information about them in memory. In
the command line where Dev Proxy runs, you should see information about API requests
that your app makes.

text

info Plugin ApiCenterMinimalPermissionsPlugin connecting to Azure...


info Listening on 127.0.0.1:8000...

Hotkeys: issue (w)eb request, (r)ecord, (s)top recording, (c)lear screen


Press CTRL+C to stop Dev Proxy

◉ Recording...

req ╭ GET https://api.northwind.com/customers/ALFKI


mock ╰ 200 /{customer-id}

Check permissions
Stop the recording by pressing s . Dev Proxy connects to the API Center instance and
compares the information about requests with the information from API Center.

text
info Plugin ApiCenterMinimalPermissionsPlugin connecting to Azure...
info Listening on 127.0.0.1:8000...

Hotkeys: issue (w)eb request, (r)ecord, (s)top recording, (c)lear screen


Press CTRL+C to stop Dev Proxy

◉ Recording...

req ╭ GET https://api.northwind.com/customers/ALFKI


mock ╰ 200 /{customer-id}
○ Stopped recording
info Checking if recorded API requests use minimal permissions as
defined in API Center...
info Loading APIs from API Center...
info Loading API definitions from API Center...
info Checking minimal permissions for API https://api.northwind.com...
info Analyzing recorded requests...
warn Calling API Northwind with excessive permissions:
customer.readwrite. Minimal permissions are: customer.read
info DONE

When Dev Proxy finishes its analysis, it creates a report in a file named
ApiCenterMinimalPermissionsPlugin_PlainTextReporter.txt with the following contents:

text

Azure API Center minimal permissions report

APIS

Northwind

x Called using excessive permissions

Permissions

- Minimal permissions: customer.read


- Permissions on the token: customer.readwrite
- Excessive permissions: customer.readwrite

Requests

- GET https://api.northwind.com/customers/ALFKI

UNMATCHED REQUESTS

No unmatched requests found.

ERRORS

No errors occurred.
Summary
Using the ApiCenterMinimalPermissionsPlugin , you can check if your app is calling APIs
using minimal permissions. The plugin compares the information about API requests
from your app with information from Azure API Center and reports on excessive
permissions. It also recommends the minimal permissions needed to call the APIs that
you're using in your app. Verifying that your app is calling APIs using minimal
permissions, helps you make your app more secure. You can run this check manually or
integrate with your CI/CD pipeline to ensure that your app is calling APIs using minimal
permissions before releasing it to production.

More information
Use Dev Proxy in CI/CD scenarios
ApiCenterMinimalPermissionsPlugin
Azure API Center
Detect minimal Microsoft Graph API
permissions
Article • 10/28/2024

Microsoft Graph exposes hundreds of endpoints that allow you to tap into data and
insights in Microsoft 365. To use these API endpoints, you need to request a correct set
of permissions.

If you work on a large solution that uses many endpoints, it can be difficult to build the
exact list of minimal permissions for your application.

To detect the minimal Microsoft Graph API permissions that your app requires:

1. Enable the GraphMinimalPermissionsPlugin plugin.


2. Start recording.
3. Use your app to issue requests as normal.
4. Stop recording.

The proxy returns a list of minimal permissions in the activity summary based on the
intercepted requests.

For example:

Console

Retrieving minimal permissions for:


- GET /me
- GET /users/{users-id}/calendars

Minimal permissions:
User.Read, Calendars.Read

By default, Dev Proxy detects minimal Delegated permissions.

To return Application permissions, update the graphMinimalPermissionsPlugin


configuration block in the devproxyrc.json file to:

JSON

{
"graphMinimalPermissionsPlugin": {
"type": "application"
}
}
Check if you're using excessive
Microsoft Graph API permissions
Article • 10/28/2024

Microsoft Graph exposes hundreds of endpoints that allow you to tap into data and
insights in Microsoft 365. To use these API endpoints, you need to request a correct set
of permissions.

A common approach to security is to apply the principle of least privilege (PoLP). This
principle applies to users, processes, and programs.

To check if your app is using more permissions than it needs:

1. Enable the GraphMinimalPermissionsGuidancePlugin plugin.


2. Start recording.
3. Use your app to issue requests as normal.
4. Stop recording.

Dev Proxy returns a list of permissions scopes that are unnecessary in the activity
summary based on the intercepted requests.

For example:

text

Evaluating delegated permissions for:

- GET /me

Permissions on the token:


AllSites.FullControl, User.Read

WARNING: The following permissions are unnecessary:


WARNING: AllSites.FullControl
Record and export proxy activity
Article • 08/05/2024

To record and export proxy activity, use the ExecutionSummaryPlugin and a reporter
plugin in your configuration file.

The following example shows how to configure the Dev Proxy to record and export
proxy activity using the ExecutionSummaryPlugin and the MarkdownReporter plugin.

JSON

{
"plugins": [
{
"name": "ExecutionSummaryPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
},
{
"name": "MarkdownReporter",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
}
],
"urlsToWatch": [
"https://jsonplaceholder.typicode.com/*"
]
}

7 Note

To export the activity, the reporter plugin must be enabled in the configuration file
and placed after the ExecutionSummaryPlugin in the plugins list. It is recommended
to place a reporter plugin at the end of the plugins list.

To record activity, Dev Proxy must be placed in record mode.

There are two ways to start recording:

Record immediately. Start proxy with --record option, for example, devproxy --
record .

Record adhoc. Press R while proxy is running.

When recording is enabled, ? Recording... is shown in the proxy output.


To generate a report from the recorded activity, stop recording.

There are two ways to stop recording:

Stop proxy. Press Ctrl + C .


Stop adhoc. Press S .

By default, activities grouped by URL. To group activity by message type, use the --
summary-group-by option.

Console

devproxy --record --summary-group-by messageType

7 Note

All recording is local. No data is sent to Microsoft.

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
How to check if my app is using
production-level APIs
Article • 02/05/2025

When building your app, you might be using APIs that are still in preview. You often use
preview APIs, when you're integrating with new features that are being built along with
your app. Before you release your app to production, you should ensure that you're
using production-level APIs. When you use stable APIs, which are supported and
covered by Service Level Agreements (SLAs), your app is more robust.

To check if your app is using production-level APIs, you can use the
ApiCenterProductionVersionPlugin plugin. This plugin compares the information about
API requests from your app with information from Azure API Center and reports on any
nonproduction API requests. It also recommends the production version of the APIs
you're using.

Before you start


To detect nonproduction API requests, you need to have an Azure API Center instance
with information about the APIs that you use in your organization.

Create an Azure API Center instance


Before you start, create an Azure API Center instance and register APIs that you use in
your organization. For each API, define the versions you use and specify their lifecycle
stage.

The ApiCenterProductionVersionPlugin uses this information to check if the APIs, that


your app is using, belong to production or nonproduction APIs.

Copy API Center information


From the Azure API Center instance Overview page, copy the name of the API Center
instance, the name of the resource group and the subscription ID. You need this
information to configure the ApiCenterProductionVersionPlugin so that it can connect
to your Azure API Center instance.

Configure Dev Proxy


To check if your app is using production-level APIs, you need to enable the
ApiCenterProductionVersionPlugin in the Dev Proxy configuration file. To create a report

of APIs that your app uses, add a reporter.

Enable the ApiCenterProductionVersionPlugin


In the devproxyrc.json file, add the following configuration:

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/rc.schema.json",
"plugins": [
{
"name": "ApiCenterProductionVersionPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "apiCenterProductionVersionPlugin"
}
],
"urlsToWatch": [
"https://jsonplaceholder.typicode.com/*"
],
"apiCenterProductionVersionPlugin": {
"subscriptionId": "aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e",
"resourceGroupName": "demo",
"serviceName": "contoso-api-center",
"workspaceName": "default"
}
}

In the subscriptionId , resourceGroupName , and serviceName properties, provide the


information about your Azure API Center instance.

In the urlsToWatch property, specify the URLs that your app uses.

 Tip

Use the Dev Proxy Toolkit Visual Studio Code extension to easily manage Dev
Proxy configuration.

Add a reporter
The ApiCenterProductionVersionPlugin produces a report of APIs that your app is using.
To view this report, add a reporter to your Dev Proxy configuration file. Dev Proxy offers
several reporters. In this example, you use the plain-text reporter.

Update your devproxyrc.json file with a reference to the plain-text reporter:

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/rc.schema.json",
"plugins": [
{
"name": "ApiCenterProductionVersionPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "apiCenterProductionVersionPlugin"
},
{
"name": "PlainTextReporter",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
}
],
"urlsToWatch": [
"https://jsonplaceholder.typicode.com/*"
],
"apiCenterProductionVersionPlugin": {
"subscriptionId": "aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e",
"resourceGroupName": "demo",
"serviceName": "contoso-api-center",
"workspaceName": "default"
}
}

Check if your app is using production-level


APIs
To check if your app is using production-level APIs, you need to connect to your Azure
subscription, run Dev Proxy, and let it intercept API requests from your app. Dev Proxy
then compares the information about the API requests with the information from Azure
API Center and reports on any nonproduction APIs.

Connect to your Azure subscription


Dev Proxy uses information from Azure API Center to determine if the APIs your app is
using are production-level. To get this information, it needs a connection to your Azure
subscription. You can connect to your Azure subscription in several ways.

Run Dev Proxy


After connecting to your Azure subscription, start Dev Proxy. If you start Dev Proxy from
the same folder where your devproxyrc.json file is located, it automatically loads the
configuration. Otherwise, specify the path to the configuration file using the --config-
file option.

When Dev Proxy starts, it checks that it can connect to your Azure subscription. When
the connection is successful, you see a message similar to:

text

info Plugin ApiCenterProductionVersionPlugin connecting to Azure...


info Listening on 127.0.0.1:8000...

Hotkeys: issue (w)eb request, (r)ecord, (s)top recording, (c)lear screen


Press CTRL+C to stop Dev Proxy

Press r to start recording API requests from your app.


Use your app
Use your app as you would normally do. Dev Proxy intercepts the API requests and
stores information about them in memory. In the command line where Dev Proxy runs,
you should see information about API requests that your app makes.

text

info Plugin ApiCenterProductionVersionPlugin connecting to Azure...


info Listening on 127.0.0.1:8000...

Hotkeys: issue (w)eb request, (r)ecord, (s)top recording, (c)lear screen


Press CTRL+C to stop Dev Proxy

◉ Recording...

req ╭ GET https://jsonplaceholder.typicode.com/posts?api-version=v1.0


api ╰ Passed through

req ╭ GET https://jsonplaceholder.typicode.com/users?api-version=beta


api ╰ Passed through

Check API versions


Stop the recording by pressing s . Dev Proxy connects to the API Center instance and
compares the information about requests with the information from API Center.

text

info Plugin ApiCenterProductionVersionPlugin connecting to Azure...


info Listening on 127.0.0.1:8000...

Hotkeys: issue (w)eb request, (r)ecord, (s)top recording, (c)lear screen


Press CTRL+C to stop Dev Proxy

◉ Recording...

req ╭ GET https://jsonplaceholder.typicode.com/posts?api-version=v1.0


api ╰ Passed through

req ╭ GET https://jsonplaceholder.typicode.com/users?api-version=beta


api ╰ Passed through
○ Stopped recording
info Checking if recorded API requests use production APIs as defined in
API Center...
info Loading APIs from API Center...
info Analyzing recorded requests...
warn Request GET https://jsonplaceholder.typicode.com/users?api-
version=beta uses API version beta which is defined as Preview. Upgrade to a
production version of the API. Recommended versions: v1.0
info DONE

When Dev Proxy finishes its analysis, it creates a report in a file named
ApiCenterProductionVersionPlugin_PlainTextReporter.txt with the following contents:

text

Non-production APIs:

GET https://jsonplaceholder.typicode.com/users?api-version=beta

Production APIs:

GET https://jsonplaceholder.typicode.com/posts?api-version=v1.0

Summary
Using the ApiCenterProductionVersionPlugin , you can check if your app is using
production-level APIs. The plugin compares the information about API requests from
your app with information from Azure API Center and reports on any nonproduction API
requests. It also recommends the production version of the APIs you're using. Verifying
what APIs your app is using, helps you ensure that your app is using stable APIs, which
are supported and covered by SLAs, making your app more robust. You can run this
check manually or integrate with your CI/CD pipeline to ensure that your app is using
production-level APIs before releasing it to production.

More information
Use Dev Proxy in CI/CD scenarios
ApiCenterProductionVersionPlugin
Azure API Center
How to find shadow APIs
Article • 02/05/2025

Using Azure API Center you can catalog APIs used in your organization. At any time, you
can tell which APIs you use in your organization. You can also tell where the API is in its
lifecycle and who to contact if there are issues. In short, having an up-to-date catalog of
APIs helps you improve the governance-, compliance-, and security posture.

When building your app, especially if you're integrating new scenarios, you might be
using APIs that aren't registered in Azure API Center. These APIs are called shadow APIs.
Shadow APIs are APIs that aren't registered in your organization. They might be APIs
that aren't yet registered, or they might be APIs that aren't meant to be used in your
organization.

To check if your app is using shadow APIs, you can use the ApiCenterOnboardingPlugin
plugin. This plugin analyzes API requests from your app and reports on any APIs that
aren't registered in API Center. Additionally, it can directly onboard new APIs to Azure
API Center.

Before you start


To detect shadow APIs, you need to have an Azure API Center instance with information
about the APIs that you use in your organization.
Create an Azure API Center instance
Before you start, create an Azure API Center instance and register APIs that you use in
your organization.

The ApiCenterOnboardingPlugin uses this information to check if the APIs, that your app
is using, are registered in your organization.

Copy API Center information


From the Azure API Center instance Overview page, copy the name of the API Center
instance, the name of the resource group and the subscription ID. You need this
information to configure the ApiCenterOnboardingPlugin so that it can connect to your
Azure API Center instance.

Configure Dev Proxy


To check if your app is using shadow APIs, you need to enable the
ApiCenterOnboardingPlugin in the Dev Proxy configuration file. To create a report of APIs

that your app uses, add a reporter.

Enable the ApiCenterOnboardingPlugin


In the devproxyrc.json file, add the following configuration:

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/rc.schema.json",
"plugins": [
{
"name": "ApiCenterOnboardingPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "apiCenterOnboardingPlugin"
}
],
"urlsToWatch": [
"https://jsonplaceholder.typicode.com/*"
],
"apiCenterOnboardingPlugin": {
"subscriptionId": "aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e",
"resourceGroupName": "demo",
"serviceName": "contoso-api-center",
"workspaceName": "default",
"createApicEntryForNewApis": false
}
}

In the subscriptionId , resourceGroupName , and serviceName properties, provide the


information about your Azure API Center instance.

In the urlsToWatch property, specify the URLs that your app uses.

 Tip

Use the Dev Proxy Toolkit Visual Studio Code extension to easily manage Dev
Proxy configuration.

Add a reporter
The ApiCenterOnboardingPlugin produces a report of APIs that your app is using. To view
this report, add a reporter to your Dev Proxy configuration file. Dev Proxy offers several
reporters. In this example, you use the plain-text reporter.

Update your devproxyrc.json file with a reference to the plain-text reporter:

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/rc.schema.json",
"plugins": [
{
"name": "ApiCenterOnboardingPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "apiCenterOnboardingPlugin"
},
{
"name": "PlainTextReporter",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
}
],
"urlsToWatch": [
"https://jsonplaceholder.typicode.com/*"
],
"apiCenterOnboardingPlugin": {
"subscriptionId": "aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e",
"resourceGroupName": "demo",
"serviceName": "contoso-api-center",
"workspaceName": "default",
"createApicEntryForNewApis": false
}
}

Check if your app is using shadow APIs


To check if your app is using shadow APIs, connect to your Azure subscription, run Dev
Proxy, and let it intercept API requests from your app. Dev Proxy then compares the
information about the API requests with the information from Azure API Center and
reports on any APIs that aren't registered in API Center.

Connect to your Azure subscription


Dev Proxy uses information from Azure API Center to determine if your app is using
shadow APIs. To get this information, it needs a connection to your Azure subscription.
You can connect to your Azure subscription in several ways.

Run Dev Proxy


After connecting to your Azure subscription, start Dev Proxy. If you start Dev Proxy from
the same folder where your devproxyrc.json file is located, it automatically loads the
configuration. Otherwise, specify the path to the configuration file using the --config-
file option.

When Dev Proxy starts, it checks that it can connect to your Azure subscription. When
the connection is successful, you see a message similar to:

text

info Plugin ApiCenterOnboardingPlugin connecting to Azure...


info Listening on 127.0.0.1:8000...

Hotkeys: issue (w)eb request, (r)ecord, (s)top recording, (c)lear screen


Press CTRL+C to stop Dev Proxy

Press r to start recording API requests from your app.


Use your app
Use your app as you would normally do. Dev Proxy intercepts the API requests and
stores information about them in memory. In the command line where Dev Proxy runs,
you should see information about API requests that your app makes.

text

info Plugin ApiCenterOnboardingPlugin connecting to Azure...


info Listening on 127.0.0.1:8000...

Hotkeys: issue (w)eb request, (r)ecord, (s)top recording, (c)lear screen


Press CTRL+C to stop Dev Proxy

◉ Recording...

req ╭ GET https://jsonplaceholder.typicode.com/posts


api ╰ Passed through

req ╭ DELETE https://jsonplaceholder.typicode.com/posts/1


api ╰ Passed through

Check shadow APIs


Stop the recording by pressing s . Dev Proxy connects to the API Center instance and
compares the information about requests with the information from API Center.

text

info Plugin ApiCenterOnboardingPlugin connecting to Azure...


info Listening on 127.0.0.1:8000...

Hotkeys: issue (w)eb request, (r)ecord, (s)top recording, (c)lear screen


Press CTRL+C to stop Dev Proxy

◉ Recording...

req ╭ GET https://jsonplaceholder.typicode.com/posts


api ╰ Passed through

req ╭ DELETE https://jsonplaceholder.typicode.com/posts/1


api ╰ Passed through
○ Stopped recording
info Checking if recorded API requests belong to APIs in API Center...
info Loading APIs from API Center...
info Loading API definitions from API Center...
When Dev Proxy finishes its analysis, it creates a report in a file named
ApiCenterOnboardingPlugin_PlainTextReporter.txt with the following contents:

text

New APIs that aren't registered in Azure API Center:

https://jsonplaceholder.typicode.com:
DELETE https://jsonplaceholder.typicode.com/posts/1

APIs that are already registered in Azure API Center:

GET https://jsonplaceholder.typicode.com/posts

Automatically onboard shadow APIs


The ApiCenterOnboardingPlugin can not only detect shadow APIs, but also automatically
onboard them to API Center. To automatically onboard shadow APIs, in the Dev Proxy
configuration file, update the createApicEntryForNewApis to true .

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/rc.schema.json",
"plugins": [
{
"name": "ApiCenterOnboardingPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "apiCenterOnboardingPlugin"
},
{
"name": "PlainTextReporter",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
}
],
"urlsToWatch": [
"https://jsonplaceholder.typicode.com/*"
],
"apiCenterOnboardingPlugin": {
"subscriptionId": "aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e",
"resourceGroupName": "demo",
"serviceName": "contoso-api-center",
"workspaceName": "default",
"createApicEntryForNewApis": true
}
}
When you run Dev Proxy with createApicEntryForNewApis set to true , it automatically
creates new API entries in Azure API Center for the shadow APIs that it detects.

Automatically onboard shadow APIs with OpenAPI spec


When you choose to automatically onboard, shadow APIs to API Center, you can have
Dev Proxy generate the OpenAPI spec for the API. Onboarding APIs with OpenAPI specs
speeds up onboarding of missing endpoints and provide you with the necessary
information about the API. When the ApiCenterOnboardingPlugin detects, that Dev Proxy
created a new OpenAPI spec, it associates it with the corresponding onboarded API in
API Center.

To automatically generate OpenAPI specs for onboarded APIs, update Dev Proxy
configuration to include the OpenApiSpecGeneratorPlugin.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/rc.schema.json",
"plugins": [
{
"name": "OpenApiSpecGeneratorPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
},
{
"name": "ApiCenterOnboardingPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "apiCenterOnboardingPlugin"
},
{
"name": "PlainTextReporter",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
}
],
"urlsToWatch": [
"https://jsonplaceholder.typicode.com/*"
],
"apiCenterOnboardingPlugin": {
"subscriptionId": "aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e",
"resourceGroupName": "demo",
"serviceName": "contoso-api-center",
"workspaceName": "default",
"createApicEntryForNewApis": true
}
}

) Important

Dev Proxy executes plugins in the order they're registered in the configuration. You
need to register the OpenApiSpecGeneratorPlugin first so that it can create OpenAPI
specs before the ApiCenterOnboardingPlugin onboards new APIs.

When you run Dev Proxy with this configuration, it automatically creates new API entries
in Azure API Center for the shadow APIs that it detects. For each new API, Dev Proxy
generates an OpenAPI spec and associates it with the corresponding onboarded API in
API Center.

text

info Plugin ApiCenterOnboardingPlugin connecting to Azure...


info Listening on 127.0.0.1:8000...

Hotkeys: issue (w)eb request, (r)ecord, (s)top recording, (c)lear screen


Press CTRL+C to stop Dev Proxy

◉ Recording...

req ╭ GET https://jsonplaceholder.typicode.com/posts


api ╰ Passed through

req ╭ DELETE https://jsonplaceholder.typicode.com/posts/1


api ╰ Passed through
○ Stopped recording
info Creating OpenAPI spec from recorded requests...
info Created OpenAPI spec file jsonplaceholder.typicode.com-
20240614104931.json
info Checking if recorded API requests belong to APIs in API Center...
info Loading APIs from API Center...
info Loading API definitions from API Center...
info New APIs that aren't registered in Azure API Center:

https://jsonplaceholder.typicode.com:
DELETE https://jsonplaceholder.typicode.com/posts/1
info Creating new API entries in API Center...
info Creating API new-jsonplaceholder-typicode-com-1718354977 for
https://jsonplaceholder.typicode.com...
info DONE

Summary
Using the ApiCenterOnboardingPlugin , you can check if your app is using shadow APIs.
The plugin analyzes API requests from your app and reports on any API requests that
aren't registered in Azure API Center. The plugin allows you to easily onboard missing
APIs to API Center. By combining the ApiCenterOnboardingPlugin plugin with the
OpenApiSpecGeneratorPlugin , you can automatically generate OpenAPI specs for the

newly onboarded APIs. You can run this check manually or integrate with your CI/CD
pipeline to ensure that your app is using registered APIs before releasing it to
production.

More information
Use Dev Proxy in CI/CD scenarios
ApiCenterOnboardingPlugin
Azure API Center
Generate an OpenAPI spec
Article • 11/12/2024

Dev Proxy allows you to generate an OpenAPI spec from the intercepted API requests
and responses. Using Dev Proxy you can quickly create an OpenAPI spec for an existing
API and benefit from the tooling that supports OpenAPI.
https://www.youtube-nocookie.com/embed/qKiR_AS8LlE?
si=VBtG3rmaSe5gYWd1&start=74

To generate an OpenAPI spec using Dev Proxy:

1. In the configuration file, enable the OpenApiSpecGeneratorPlugin plugin:

JSON

{
"plugins": [
{
"name": "OpenApiSpecGeneratorPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
}
]
// [...] shortened for brevity
}

2. In the configuration file, to the list of URLs to watch, add the URL of the API for
which you want to generate an OpenAPI spec:

JSON

{
"urlsToWatch": [
"https://api.example.com/*",
]
// [...] shortened for brevity
}

 Tip

To create better OpenAPI specs, consider using a local language model with
Dev Proxy. For more information, see Use a local language model.

3. Start Dev Proxy:


Console

devproxy

4. Start recording requests by pressing r

5. Perform the requests you want to include in the OpenAPI spec

6. Stop recording requests by pressing s

7. Dev Proxy generates an OpenAPI spec and saves it to a file in the current directory.
Dev Proxy names the file after the host name of the API followed by the current
date and time, for example: api.example.com-20231219091700.json .


Generate a TypeSpec file
Article • 05/02/2025

Dev Proxy allows you to generate a TypeSpec file from the intercepted API requests and
responses. Using Dev Proxy you can quickly create a TypeSpec file for an existing API and
benefit from the tooling that supports TypeSpec.

To generate a TypeSpec file using Dev Proxy:

1. In the configuration file, enable the TypeSpecGeneratorPlugin plugin:

JSON

{
"plugins": [
{
"name": "TypeSpecGeneratorPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
}
]
// [...] shortened for brevity
}

2. Optionally, configure the plugin in the configuration file:

JSON

{
"typeSpecGeneratorPlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/typespecgeneratorplugin.schema.json",
"ignoreResponseTypes": false
}
// [...] shortened for brevity
}

3. In the configuration file, to the list of URLs to watch, add the URL of the API for which you
want to generate a TypeSpec file:

JSON

{
"urlsToWatch": [
"https://api.example.com/*",
]
// [...] shortened for brevity
}

 Tip

To create better TypeSpec files, consider using a local language model with Dev
Proxy. Using a local language model, the TypeSpecGeneratorPlugin generates clearer
operation IDs and descriptions, giving you a better starting point for your TypeSpec
file. For more information, see Use a local language model.

4. Start Dev Proxy:

Console

devproxy

5. Start recording requests by pressing r

6. Perform the requests you want to include in the TypeSpec file

7. Stop recording requests by pressing s

8. Dev Proxy generates a TypeSpec file and saves it to a file in the current directory. Dev
Proxy names the file after the host name of the API followed by the current date and time,
for example: api.example.com-20231219091700.tsp .


Next steps
Learn more about the TypeSpecGeneratorPlugin.

TypeSpecGeneratorPlugin
Update my application code to use
Microsoft Graph JavaScript SDK
Article • 01/09/2024

The Microsoft Graph JavaScript SDK comes with features that simplifies your code and
let you focus on building your app.

Using the SDK makes it easier for you to:

Handle API errors for when things don't work as expected, such as when services
throttle under heavy load
Perform complex API operations like batch requests
Handle binary responses, such as obtaining the photo of a user

Migrate from fetch to the Graph JavaScript SDK


If you use the fetch API to call APIs in your JavaScript app, you might have code similar
to the following:

JavaScript

const msalClient = new msal.PublicClientApplication({


auth: {
clientId: appId
}
});

function getAccessToken(msalClient) {
const accounts = msalClient.getAllAccounts();

if (accounts.length > 0) {
const accessTokenRequest = {
scopes: [
'https://graph.microsoft.com/User.Read'
],
account: accounts[0]
};

return msalClient.acquireTokenSilent(accessTokenRequest)
.then(response => response.accessToken)
.catch(error => {
console.log(error);
console.log("silent token acquisition fails. acquiring token using
redirect");
if (error instanceof msal.InteractionRequiredAuthError) {
return msalClient.acquireTokenRedirect(accessTokenRequest);
}
});
}
else {
return Promise.reject('Sign in');
}
}

msalClient
.loginPopup()
.then(response => getAccessToken(msalClient))
.then(accessToken => fetch('https://graph.microsoft.com/v1.0/me', {
method: 'GET',
headers: {
authorization: `Bearer ${accessToken}`
}
}))
.then(response => response.json())
.then(json => {
// do something here
});

To use the Graph JavaScript SDK, you'd change the code to:

JavaScript

const msalClient = new msal.PublicClientApplication({


auth: {
clientId: appId
}
});

function getGraphClient(account) {
const authProvider = new
MSGraphAuthCodeMSALBrowserAuthProvider.AuthCodeMSALBrowserAuthenticationProv
ider(msalClient, {
account,
scopes: [
'https://graph.microsoft.com/User.Read'
],
interactionType: msal.InteractionType.Popup,
});

return MicrosoftGraph.Client.initWithMiddleware({ authProvider });


}

msalClient
.loginPopup()
.then(response => {
const accounts = msalClient.getAllAccounts();

if (accounts.length > 0) {
const graphClient = getGraphClient(accounts[0]);
return graphClient.api('/me').get();
}
else {
return Promise.reject('Sign in');
}
})
.then(json => {
// do something here
});

Handle API errors


One of the most common API errors that applications using Microsoft Graph experience
when used at scale is throttling. It occurs, when the server is under heavy load.
Throttling decreases the load on the server to keep the service up.

Since throttling rarely occurs on developer tenants, often developers call the API without
properly handling errors:

JavaScript

fetch('https://graph.microsoft.com/v1.0/me', {
method: 'GET',
headers: {
authorization: `Bearer ${accessToken}`
}
})
.then(response => response.json())
.then(json => {
// do something here
});

The proper way to handle throttling errors with fetch API would be to extend the call to
watch out for 429 throttling errors and wait before calling the API again for the number
of seconds designated in the retry-after response header. Updated code would look
as follows:

JavaScript

function sleep(milliseconds) {
return new Promise((resolve) => setTimeout(resolve, milliseconds));
}

async function fetchAndRetryIfNecessary(callAPIFn) {


const response = await callAPIFn();

if (response.status === 429) {


const retryAfter = response.headers.get('retry-after');
await sleep(retryAfter * 1000);
return fetchAndRetryIfNecessary(callAPIFn);
}

return response;
}

const response = await fetchAndRetryIfNecessary(async () => (


await fetch('https://graph.microsoft.com/v1.0/me', {
method: 'GET',
headers: {
authorization: `Bearer ${accessToken}`
}
})
));
const json = await response.json();
// do something here

An easier way to handle throttling, and other errors, is to use the Graph JavaScript SDK,
which handles errors for you.

JavaScript

const json = await graphClient.api('/me').get();


// do something here

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
Use preset configurations
Article • 04/08/2024

Using presets you can quickly configure Dev Proxy to work with common scenarios. A
preset is a JSON file that contains the configuration for Dev Proxy. The file defines which
plugins Dev Proxy uses and how they're configured.

We include several preset configurations with Dev Proxy. You can find them in the
presets folder in the Dev Proxy installation directory. You can also create your own

preset configurations.

 Tip

Check out Dev Proxy presets created by the community in the Sample Solution
Gallery.

To use a preset, use the --config-file option and pass the path to the preset file:

Console

devproxy --config-file presets/microsoft-graph-rate-limiting.json

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
Change logging level
Article • 04/08/2024

By default, the proxy is set to log information level events. These events are messages
not related to requests, only the events related to the working of Dev Proxy.

To change the default logging level, update the logLevel setting in the devproxyrc.json
file.

JSON

{
"logLevel": "debug"
}

To change the logging level at run time, use the --log-level command line option.

Console

devproxy --log-level debug

For the list of available logging levels, see the Proxy settings page.

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
Clear the output
Article • 04/08/2024

To clear the proxy output in your command prompt, press c on your keyboard.

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
Use local language model with Dev Proxy
Article • 04/28/2025

By connecting Dev Proxy to a local language model, you can improve Dev Proxy's functionality.
Select Dev Proxy plugins use the language model to improve their output, where natural
language is involved. By using a local language model, you can benefit from the improved
functionality without incurring extra costs.

Prerequisites
Dev Proxy supports language model hosts that expose OpenAI-compatible APIs. It also has
support for Ollama APIs. To configure a local language model host, follow the instructions in its
documentation.

Configure Dev Proxy to use a local language model


To configure Dev Proxy to use a local language model, use the languageModel setting in the
devproxyrc.json file.

JSON

{
"languageModel": {
"enabled": true
}
}

You can use the following options as part of the languageModel setting:

ノ Expand table

Option Description Default value

cacheResponses Specifies whether to cache responses from the language true


model.

client The type of the client to use. Allowed values: Ollama , OpenAI
OpenAI

enabled Specifies whether to use a local language model. false

model The name of the language model to use. llama3.2

url The URL of the local language model client. http://localhost:11434/v1/


By default, Dev Proxy uses the standard Ollama configuration with the llama3.2 model using
Ollama's OpenAI-compatible APIs. It also caches responses from the language model, which
means, that for the same prompt, you get an immediate response without waiting for the
language model to process it.

) Important

When using a local language model, be sure to start your local language model client
before starting Dev Proxy.

Dev Proxy plugins that can use a local language


model
The following Dev Proxy plugins use a local language model if available:

OpenAIMockResponsePlugin
OpenApiSpecGeneratorPlugin
TypeSpecGeneratorPlugin
Refresh local Microsoft Graph database
Article • 01/24/2024

The GraphSelectGuidancePlugin uses a local SQLite database to store the OpenAPI


specifications for both the v1.0 and beta endpoints of Microsoft Graph. This database is
automatically created and updated for you, but there maybe occasions when you want
to refresh this database yourself.

Execute devproxy msgraphdb in your proxy installation folder to rebuild and update
your local database.

Here's sample output of running the command.

text

Checking for updated OpenAPI files...


Downloaded OpenAPI file from
https://raw.githubusercontent.com/microsoftgraph/msgraph-
metadata/master/openapi/v1.0/openapi.yaml to <devproxy-path>\graph-v1_0-
openapi.yaml
Downloaded OpenAPI file from
https://raw.githubusercontent.com/microsoftgraph/msgraph-
metadata/master/openapi/beta/openapi.yaml to <devproxy-path>\graph-beta-
openapi.yaml
Loading OpenAPI files...
Creating database...
Filling database...
Inserted 17306 endpoints in the database
Microsoft Graph database successfully updated

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
Use Dev Proxy in a Docker container
Article • 04/02/2025

When using Dev Proxy, you can choose to run it directly on your machine or in a Docker
container. Running Dev Proxy in Docker is a great way to isolate it from your local
environment. It also offers you a consistent way of using Dev Proxy between your local
machine and CI/CD environments.

Use the Dev Proxy Docker image


For your convenience, we provide a ready to use Docker image with Dev Proxy. You can
use it to run Dev Proxy in a Docker container. You can pull the image from the GitHub
Container Registry, by using the following command:

Bash

docker pull ghcr.io/dotnet/dev-proxy:latest

7 Note

To try the latest preview features, use the beta version of the Dev Proxy container.

Bash

docker pull ghcr.io/dotnet/dev-proxy:beta

If you use Dev Proxy in a CI/CD pipeline, consider using a specific version of the image,
instead of latest or beta . This way, you can ensure that your pipeline isn't affected by
any breaking changes introduced in the latest version of Dev Proxy. For example, to use
Dev Proxy version 0.26.0, use the following command:

Bash

docker pull ghcr.io/dotnet/dev-proxy:0.26.0

Start the Dev Proxy container


To start the Dev Proxy container, use the following command:
Bash

docker run \
# remove the container when it exits
--rm \
# run the container interactively
-it \
# map Dev Proxy ports to the host
-p 8000:8000 -p 8897:8897 \
# map volumes to the host. Create the `cert` folder in the current
working directory before running the command
-v ${PWD}:/config -v ${PWD}/cert:/home/devproxy/.config/dev-
proxy/rootCert \
# specify the image to use
ghcr.io/dotnet/dev-proxy:0.26.0

After you run the command, Dev Proxy starts automatically and listens for traffic on port
8000. Since it's running in a Docker container, it doesn't automatically register as a
system proxy on the host to intercept web requests. Instead, you need to manually
configure the system proxy on your host or configure the proxy for your application.

By running the container interactively (using the -it options), you can control Dev
Proxy from the command line. Interacting with Dev Proxy is helpful, for example, for
starting and stopping recording, clearing the screen, etc. If you start the container in the
background, you can still control Dev Proxy using the Dev Proxy API.

Parameters
The Dev Proxy Docker contains several parameters that you can use to customize its
behavior.

Ports
The image exposes the following ports:

8000 - the port on which Dev Proxy listens for incoming traffic.
8897 - the port on which Dev Proxy exposes its API. You can use it to interact with
Dev Proxy programmatically.

) Important

Be sure to map both ports to your host, so that you can access Dev Proxy from your
local machine and use Dev Proxy Toolkit .
Volumes
The image exposes the following volumes:

/config - the current working directory from which the container starts Dev Proxy.
If the folder you map contains a devproxyrc.json file, Dev Proxy automatically uses
it to configure itself.
/home/devproxy/.config/dev-proxy/rootCert - the folder in which Dev Proxy
stores its root certificate. By mapping the volume to your host, you can easily
access the root certificate and install it in your system or browser.

 Tip

Alternatively to mapping the root certificate to your host, you can use the Dev
Proxy API to download the public key of the root certificate in the PEM (Privacy
Enhanced Mail) format. To download the certificate, call the GET
http://127.0.0.1:8897/proxy/rootCertificate?format=crt endpoint.

Using Dev Proxy in Docker


When you start the Dev Proxy container, it automatically starts Dev Proxy listening for
incoming traffic on port 8000.

Default configuration
Dev Proxy looks for the devproxyrc.json file in the folder you map to the /config
volume. If it finds the file, it uses it to configure itself. If it doesn't find the file, it uses the
default configuration.

Custom configuration
You can use custom configuration for Dev Proxy by creating the devproxyrc.json file in
the folder you map to the /config volume. Alternatively, you can specify the
configuration file using the --config-file parameter when starting Dev Proxy. For
example, to use the myconfig.json file, use the following command:

Bash

docker run \
# remove the container when it exits
--rm \
# run the container interactively
-it \
# map Dev Proxy ports to the host
-p 8000:8000 -p 8897:8897 \
# map volumes to the host. Create the `cert` folder in the current
working directory before running the command
-v ${PWD}:/config -v ${PWD}/cert:/home/devproxy/.config/dev-
proxy/rootCert \
# specify the image to use
ghcr.io/dotnet/dev-proxy:0.26.0 \
# specify the configuration file to use
--config-file /config/myconfig.json

The configuration file you specify must be accessible from the container. If you use a
relative path, it must be relative to the /config volume.

Other options
If you want to use other options, you can specify them in the same way as you would
when running Dev Proxy directly on your machine. For example, to specify the URLs to
watch, use the following command:

Bash

docker run \
# remove the container when it exits
--rm \
# run the container interactively
-it \
# map Dev Proxy ports to the host
-p 8000:8000 -p 8897:8897 \
# map volumes to the host. Create the `cert` folder in the current
working directory before running the command
-v ${PWD}:/config -v ${PWD}/cert:/home/devproxy/.config/dev-
proxy/rootCert \
# specify the image to use
ghcr.io/dotnet/dev-proxy:0.26.0 \
# specify the URLs to watch
--urls-to-watch "https://example.com/*"
Use Dev Proxy with Node.js applications
Article • 07/09/2024

There's no standard way of enabling proxies for Node.js applications. Whether you can
use proxy, depends on the library you're using to make HTTP requests. Typically, you
need to update your code to configure the proxy. You can however use the global-
agent package to enable proxy support for your Node.js application with minimal code

changes.

Native Node.js fetch API


In v17.5.0, Node.js introduces experimental support for the fetch API. Unfortunately,
this API is still limited and doesn't support configuring a proxy. If you want to use Dev
Proxy with Node.js, you need to use a different library for making HTTP requests.

global-agent
global-agent is a popular library that provides a global HTTP/HTTPS agent for
Node.js. It allows you to specify the proxy using environment variables. The benefit of
using global-agent is that you don't need to change how you issue HTTP requests in
your application to use Dev Proxy.

Here's an example of how you can use global-agent in a Node.js application that uses
node-fetch :

JavaScript

import fetch from 'node-fetch';


import { bootstrap } from 'global-agent';
bootstrap();

(async () => {
const result = await fetch('https://jsonplaceholder.typicode.com/posts');
const jsonResult = await result.json();
console.log(JSON.stringify(jsonResult, null, 2));
})();

Here's how you can use global-agent with Node.js and the standard https module:

JavaScript
const https = require('https');
const globalAgent = require('global-agent');
globalAgent.bootstrap();

https.get('https://jsonplaceholder.typicode.com/posts', (resp) => {


let data = '';
resp.on('data', (d) => {
data += d;
});
resp.on('end', () => {
console.log(JSON.parse(data));
});
resp.on('error', (err) => {
console.error(err);
});
});

When starting your application, specify the proxy using the GLOBAL_AGENT_HTTP_PROXY
environment variable and ignore certificate errors.

Console

NODE_TLS_REJECT_UNAUTHORIZED=0 GLOBAL_AGENT_HTTP_PROXY=http://127.0.0.1:8000
node global-node-fetch.mjs

node-fetch
node-fetch is a popular library that provides a fetch implementation for Node.js.
node-fetch doesn't support specifying the proxy using environment variables. Instead,

you need to create a custom agent and pass it to the fetch method.

Here's an example of how you can use node-fetch with Dev Proxy by defining an agent
using the https-proxy-agent package.

JavaScript

const fetch = require('node-fetch');


const { HttpsProxyAgent } = require('https-proxy-agent');

(async () => {
// Create a custom agent pointing to Dev Proxy
const agent = new HttpsProxyAgent('http://127.0.0.1:8000');
// Pass the agent to the fetch method
const result = await fetch('https://jsonplaceholder.typicode.com/posts', {
agent });
const jsonResult = await result.json();
console.log(JSON.stringify(jsonResult, null, 2));
})();

Axios
Axios is another popular library for making HTTP requests in Node.js. Axios allows you
to specify the proxy using environment variables or specify the agent directly in the
request configuration.

Use Axios and Dev Proxy with environment variables


When you use Dev Proxy with Axios and specify the proxy using environment variables,
you don't need to change your code. All you need to do is to set the https_proxy
environment variable and Axios uses it to make requests.

JavaScript

import axios from 'axios';

(async () => {
const result = await
axios.get('https://jsonplaceholder.typicode.com/posts');
const response = result.data;
console.log(JSON.stringify(response, null, 2));
})();

Specify the https_proxy environment variable either globally or when starting your app.

Console

https_proxy=http://127.0.0.1:8000 node axios.mjs

Got
Similar to node-fetch , Got doesn't support specifying the proxy using environment
variables. Instead, you need to create a custom agent and pass it to the request.

Here's an example of how you can use Got with Dev Proxy:

JavaScript

import got from 'got';


import { HttpsProxyAgent } from 'https-proxy-agent';
(async () => {
// Create a custom agent pointing to Dev Proxy
const agent = new HttpsProxyAgent('http://127.0.0.1:8000');
const result = await got('https://jsonplaceholder.typicode.com/posts', {
// Pass the agent to the fetch method
agent: {
https: agent
},
// Disable certificate validation
https: {
rejectUnauthorized: false
}
}).json();
console.log(JSON.stringify(result, null, 2));
})();

SuperAgent
SuperAgent doesn't support specifying the proxy using environment variables. To use
Dev Proxy with SuperAgent, you need to install the superagent-proxy plugin and
configure the proxy using the proxy method.

JavaScript

const superagent = require('superagent');


require('superagent-proxy')(superagent);

(async () => {
const result = await superagent
.get('https://jsonplaceholder.typicode.com/posts')
.proxy('http://127.0.0.1:8000')
// Disable certificate validation
.disableTLSCerts();
console.log(JSON.stringify(result.body, null, 2));
})();

Known issues
When you use Dev Proxy with Node.js, you might encounter the following issues.

UNABLE_TO_VERIFY_LEAF_SIGNATURE error

When you use Dev Proxy with Node.js, you get an error similar to:

plaintext
/Users/user/my-app/node_modules/node-fetch/lib/index.js:1501
reject(new FetchError(`request to ${request.url}
failed, reason: ${err.message}`, 'system', err));
^
FetchError: request to https://jsonplaceholder.typicode.com/posts failed,
reason: unable to verify the first certificate
at ClientRequest.<anonymous> (/Users/user/my-app/node_modules/node-
fetch/lib/index.js:1501:11)
at ClientRequest.emit (node:events:518:28)
at TLSSocket.socketErrorListener (node:_http_client:495:9)
at TLSSocket.emit (node:events:518:28)
at emitErrorNT (node:internal/streams/destroy:169:8)
at emitErrorCloseNT (node:internal/streams/destroy:128:3)
at process.processTicksAndRejections
(node:internal/process/task_queues:82:21) {
type: 'system',
errno: 'UNABLE_TO_VERIFY_LEAF_SIGNATURE',
code: 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'
}

To fix this issue, you need to set the NODE_TLS_REJECT_UNAUTHORIZED environment variable
to 0 . You can define it globally, or in-line when starting your app.

Console

NODE_TLS_REJECT_UNAUTHORIZED=0 node index.js

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
Use Dev Proxy with Node.js applications
running in Docker
Article • 04/08/2024

If you run your Node.js application in a Docker container and want to use Dev Proxy,
follow the general guidance for using Dev Proxy with Node.js applications.

Because your app is running inside a Docker container and Dev Proxy is running on your
host, you need to configure the proxy to point to the IP address of your computer.

When using Dev Proxy on macOS, you need to attach it to the 0.0.0.0 address to make
it accessible from the Docker container. To configure the IP address for Dev Proxy, start
it with the following command:

Console

devproxy --ip-address 0.0.0.0

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
Use Dev Proxy with JavaScript Azure
Functions
Article • 02/05/2024

If you build Azure Functions using JavaScript and want to use Dev Proxy, follow the
general guidance for using Dev Proxy with Node.js applications.

To be able to easily switch between using Dev Proxy in development and not using it in
production, you can best configure the proxy in your Azure Functions app using
environment variables. Change the local.settings.json file to include the HTTPS_PROXY
environment variable. Additionally, disable certificate validation to allow the Azure
Functions app to trust the self-signed certificate used by Dev Proxy.

JSON

{
"IsEncrypted": false,
"Values": {
"FUNCTIONS_WORKER_RUNTIME": "node",
"AzureWebJobsFeatureFlags": "EnableWorkerIndexing",
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"HTTP_PROXY": "http://127.0.0.1:8000",
"NODE_TLS_REJECT_UNAUTHORIZED": "0"
}
}

In your Azure Functions app, use the process.env object to read the environment
variables and configure the proxy for your HTTP requests.

JavaScript

import { app, HttpRequest, HttpResponseInit, InvocationContext } from


"@azure/functions";
import fetch from 'node-fetch';
import { HttpsProxyAgent } from 'https-proxy-agent';

export async function MyFnHttpTrigger(request: HttpRequest, context:


InvocationContext): Promise<HttpResponseInit> {
const options = process.env.HTTP_PROXY ? { agent: new
HttpsProxyAgent(process.env.HTTP_PROXY) } : {};
const resp = await fetch('https://jsonplaceholder.typicode.com/posts',
options);
const data = await resp.json();
return {
status: 200,
jsonBody: data
};
};

app.http('MyFnHttpTrigger', {
methods: ['GET', 'POST'],
authLevel: 'anonymous',
handler: MyFnHttpTrigger
});

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
Use Dev Proxy with .NET applications
Article • 04/08/2024

.NET automatically uses the system proxy settings. If you want to use Dev Proxy with
your .NET application, you don't need to make any changes to your application. Start
Dev Proxy and it will automatically intercept web requests made by your .NET
application.

Following is a simple .NET app that makes a web request to


https://jsonplaceholder.typicode.com/posts :

C#

var client = new HttpClient();


var response = await
client.GetStringAsync("https://jsonplaceholder.typicode.com/posts");
Console.WriteLine(response);

To simulate errors from this request, start Dev Proxy with the default preset, which is
configured for intercepting requests to https://jsonplaceholder.typicode.com/* .

Console

devproxy

When you run your .NET application, Dev Proxy intercepts the request and returns a 429
error.

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
Use Dev Proxy with .NET applications
running in Docker
Article • 06/18/2024

If you run your .NET application in a Docker container and want to use Dev Proxy, there
are several steps you need to follow to make it work.

Configure proxy for your Docker container


Because your .NET app is running inside a Docker container and Dev Proxy is running on
your host, you need to configure the proxy to point to the IP address of your computer
( http://192.0.2.13 in the following example). .NET uses the HTTPS_PROXY environment
variable to configure the proxy for its HTTP client. To configure the variable for your
Docker container, use the --env, -e option when starting the container:

Console

docker run --rm -it -v $(pwd):/usr/src/app -e


HTTPS_PROXY=http://192.0.2.13:8000 mcr.microsoft.com/dotnet/sdk:8.0 bash

Handle SSL certificates


Dev Proxy uses its own SSL certificate to inspect HTTPS traffic intercepted from your
application. When you install Dev Proxy on your computer, it generates a self-signed
SSL certificate and adds it to the list of trusted certificates. However, when running your
application in a Docker container, the container doesn't have access to the SSL
certificate installed on your computer. There are two ways for you to handle SSL
certificates when using Dev Proxy with .NET applications running in Docker containers.

Configure Dev Proxy certificate in your Docker container


To allow Dev Proxy to inspect HTTPS requests, you can configure the Dev Proxy SSL
certificate as trusted in your Docker container.

) Important

Because Docker doesn't persist changes to a container after closing it, you'll need
to repeat these steps each time you start the container. To avoid this, create a
custom Docker image with the following steps included.

Start, by exporting the Dev Proxy certificate to PEM.

To export the Dev Proxy certificate to PEM on Windows, you need openssl . This
example assumes you use openssl that's provided together with git but you can install
it separately as well.

Adjust the Dev Proxy and git installation directory, and run the following script in
PowerShell.

PowerShell

$proxyPath = "C:\apps\devproxy"
$gitPath = "C:\Program Files\Git"

# convert Dev Proxy root certificate to PEM


$executable = "${gitPath}\usr\bin\openssl.exe"
$arguments = 'pkcs12 -in "{0}\rootCert.pfx" -out "{0}\rootCert.crt" -nodes'
-f $proxyPath
Start-Process -FilePath $executable -ArgumentList $arguments -NoNewWindow -
Wait

# Read PEM contents


$content = Get-Content "$proxyPath\rootCert.crt"

# Find the indices of the begin and end certificate lines


$beginIndex = $content.IndexOf("-----BEGIN CERTIFICATE-----")
$endIndex = $content.IndexOf("-----END CERTIFICATE-----")

# If both lines are found


if ($beginIndex -ne -1 -and $endIndex -ne -1) {
# Trim the content to only include the certificate
$content = $content[$beginIndex..$endIndex]
}

# Write the updated content back to the file


$content | Out-File "$proxyPath\dev-proxy-ca.crt"

When prompted to enter the password, press Enter without typing anything.

Next, copy the certificate to your Docker container. The easiest way to copy the
certificate is to copy it to the project folder, which you mount to the container.

Then, in the Docker container, trust the certificate. If you're using the
mcr.microsoft.com/dotnet/sdk image, you can use the following commands:

Console
# change to the directory where your application is located
cd /usr/app/src
# copy the certificate to the trusted certificates directory
cp dev-proxy-ca.crt /usr/local/share/ca-certificates
# update the trusted certificates
update-ca-certificates

Ignore SSL certificate validation in your .NET application


Another way to handle SSL certificates when using Dev Proxy with .NET applications
running in Docker containers is to ignore SSL certificate validation in your application.
This approach requires you to modify your application code.

In your application, add the following code to ignore SSL certificate validation:

C#

ServicePointManager.ServerCertificateValidationCallback = (sender,
certificate, chain, sslPolicyErrors) => true;

U Caution

Be sure to remove this code before deploying your application to production.

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
be found on GitHub, where you Select a link to provide feedback:
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
Use Dev Proxy with .NET Aspire
applications
Article • 04/08/2024

.NET Aspire is an opinionated, cloud ready stack for building observable, production
ready, distributed applications. It's built on top of .NET and provides a modern, fast, and
scalable platform for building web applications.

If you want to use Dev Proxy with your .NET Aspire application, you first need to find out
the internal URLs that your application uses to communicate with other services. Once
you have the URLs, configure Dev Proxy to intercept the requests and simulate different
scenarios, such as throttling, errors, or latency.

Discover internal URLs


To discover the internal URLs that your .NET Aspire application uses:

1. In a command prompt, start the app host project

Console

dotnet run --project src/MyApp.Host/MyApp.Host.csproj

2. In the web browser, open the dashboard of your .NET Aspire application

3. From the list of services, find the service that you want to simulate errors for, and
note its internal URL, for example http://localhost:5222

4. In a command prompt, stop the app host project, by pressing Ctrl + C

Start Dev Proxy monitoring the internal URLs


Start Dev Proxy and configure it to intercept the requests to the internal URLs that you
discovered in the previous step:

Console

devproxy --urls-to-watch "http://localhost:5222/*"

 Tip
You can specify multiple URLs to watch, for example --urls-to-watch
"http://localhost:5222/*" "http://localhost:5223/*"

Start your .NET Aspire application to use Dev


Proxy
Start your .NET Aspire application and configure it to use Dev Proxy:

Console

HTTP_PROXY=http://127.0.0.1:8000 dotnet run --project


src/MyApp.Host/MyApp.Host.csproj

When you use your .NET Aspire application, Dev Proxy intercepts the requests and
simulates the scenarios that you configured.

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
Use Dev Proxy with SharePoint
Framework (SPFx) solutions
Article • 02/07/2024

SharePoint Framework (SPFx) is a development model for extending SharePoint,


Microsoft Teams, Microsoft Viva and Microsoft 365. When you build SPFx solutions, you
can use Dev Proxy to intercept web requests made by your solution and see how it
handles API errors.

Intercept web requests made by your SPFx


solution
SharePoint Framework solutions are client-side applications that run in the web browser.
Before you start Dev Proxy, you need to configure it to intercept requests made by your
SPFx solution. Often, you want to intercept requests to Microsoft Graph and SharePoint
REST APIs. If you use custom APIs, you want to intercept requests to them as well. You
can define the URLs to intercept in the urlsToWatch property in the Dev Proxy
configuration file.

JSON

{
// [...] trimmed for brevity
"urlsToWatch": [
"https://graph.microsoft.com/*",
"https://*.sharepoint.com/*"
// other URLs to watch
]
}

 Tip

When using Dev Proxy with SharePoint Framework Dev Proxy solutions, use the
SPFx preset from the Sample Solution Gallery. It contains the common
configuration for intercepting web requests made by SPFx solutions, including
requests to Microsoft Graph and SharePoint REST APIs.

When you start Dev Proxy on your machine, it automatically intercepts web requests
made by your SPFx solution and simulates configured responses. You don't need to
change your SPFx solution to use Dev Proxy.
Configure Dev Proxy to not intercept
SharePoint Framework workbench requests
When building SPFx solutions, you use the SharePoint Framework workbench to test
your web parts. SharePoint Framework workbench runs in the web browser and uses
SharePoint APIs to load web parts. By default, Dev Proxy intercepts all web requests
from your web browser, including the requests made by the SharePoint Framework
workbench. As a result, it can prevent you from testing your web parts.

To avoid Dev Proxy blocking the requests made by the SharePoint Framework
workbench, configure Dev Proxy to not intercept requests to the web part API. In your
Dev Proxy configuration file, exclude the API by updating the urlsToWatch property.

JSON

{
// [...] trimmed for brevity
"urlsToWatch": [
"!https://*.sharepoint.com/_api/web/GetClientSideComponents*"
// other URLs to watch
]
}

 Tip

If you use the SPFx preset from the Sample Solution Gallery, it already excludes this
URL from being intercepted by Dev Proxy.

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
be found on GitHub, where you Select a link to provide feedback:
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
Use Dev Proxy in CI/CD scenarios
Article • 06/25/2024

Using Dev Proxy in CI/CD scenarios is a great way to test your applications in a
controlled environment. When you combine Dev Proxy with tests that generate API
requests in your application, you can cover a wide range of scenarios: from ensuring
that your app doesn't use shadow- or nonproduction APIs to checking that it uses
minimal Microsoft Graph permissions. While the exact configuration steps vary
depending on your CI/CD system, here are some general principles that you should
follow.

Configure your runner


When you use Dev Proxy on your local machine, it runs interactively, waiting for you to
control it by pressing keys. When you run it in a CI/CD pipeline, you can't control it with
keys. To instruct Dev Proxy that it should run non-interactively, set the CI environment
to 1 or true .

7 Note

Most CI/CD runners already have the CI environment variable set. However, if
you're using a custom runner, you might need to set it manually.

When Dev Proxy detects the CI environment variable, it doesn't wait for key presses.
You can then stop Dev Proxy gracefully by sending a SIGINT signal to the process.
Closing Dev Proxy gracefully is necessary when you record requests and want Dev Proxy
to analyze them using its reporting plugins. Without the CI environment variable, Dev
Proxy would wait for you to press Ctrl + C . The only way to stop it would be to
forcefully close its process using kill -9 or kill -KILL , which stops Dev Proxy
immediately and prevents it from analyzing the recorded requests.

Install Dev Proxy


In most cases, your runner doesn't have Dev Proxy installed. So before you can use Dev
Proxy, you need to install it. The installation steps depend on the operating system that
your runner uses.

 Tip
To speed up your pipeline, consider caching the Dev Proxy installation folder. This
way, you won't need to download the Dev Proxy every time you run your pipeline.
For the exact steps, refer to the documentation of your CI/CD system.

When installing Dev Proxy in a CI/CD setup, you'll likely want to pin the version of Dev
Proxy that you install. Pinning the version ensures that your pipeline uses the same
version of Dev Proxy every time you run it. The exact steps to pin a version depend on
the operating system of your runner. Here's an example of how you can pin the version
of Dev Proxy on a Linux-based runner:

Bash

# install Dev Proxy v0.18.0


bash -c "$(curl -sL https://aka.ms/devproxy/setup.sh)" -- v0.18.0

Run Dev Proxy from a script


When you run Dev Proxy in a CI/CD pipeline, you need to start it from a script. Starting
Dev Proxy from a script is necessary, because to close Dev Proxy gracefully, you need to
send a SIGINT signal to its process. Closing a process using SIGINT is possible only from
a script with job control enabled. If you start Dev Proxy directly from your CI/CD system,
the Dev Proxy process ignores the SIGINT signal, and keeps running.

Here's an example of a bash script with job control enabled that starts Dev Proxy:

Bash

# enable job control so that we can send SIGINT to Dev Proxy


set -m

# the rest of the script using Dev Proxy

Run Dev Proxy


After installing Dev Proxy, you need to start it. When starting Dev Proxy in a CI/CD
pipeline it's important, that you start it in the background. Otherwise, your pipeline is
blocked until you stop Dev Proxy.

If you're using a Linux-based runner, you can start Dev Proxy in the background by
adding & at the end of the command, for example ./devproxy/devproxy & .
Wait for Dev Proxy to start
When you start Dev Proxy in the background, your script continues executing
immediately. However, Dev Proxy needs some time to start. To ensure that Dev Proxy is
ready before you start running your tests, wait for it to start. To wait for Dev Proxy to
start, log its output to a file, and then check if Dev Proxy is listening for web requests,
for example:

Bash

# log file path


log_file=devproxy.log

# start Dev Proxy in the background


# log Dev Proxy output to the log file
# log stdout and stderr to the file
./devproxy/devproxy > $log_file 2>&1 &

# store the Dev Proxy process ID


proxy_pid=$!

# wait for init


echo "Waiting for Dev Proxy to start..."
while true; do
if grep -q "Listening on 127.0.0.1:8000" $log_file; then
break
fi
sleep 1
done

# the rest of your script

Record requests
If you want to analyze API requests issued by your app, start Dev Proxy in the recording
mode. You can start Dev Proxy with recording, using the --record command-line
argument, for example:

Bash

./devproxy/devproxy --record

Stop Dev Proxy


After you're done with your tests, stop Dev Proxy, by sending a SIGINT signal to it. You
can send the SIGINT signal using the kill command, for example:

Bash

kill -INT $proxy_pid

After you stop the Dev Proxy process, it can take a moment for it to fully close. This is
especially the case, when you configure Dev Proxy to analyze recorded requests. To
ensure that Dev Proxy finished processing the recorded requests, wait for the process to
close, for example:

Bash

echo "Waiting for Dev Proxy to complete..."


while true; do
if grep -q -e "DONE" -e "No requests to process" -e "An error occurred in
a plugin" $log_file; then
break
fi
sleep 1
done

When all recording plugins finish running, Dev Proxy prints the DONE message to the
output. If there were no requests to process, Dev Proxy prints the No requests to
process message. If an error occurred in a plugin, Dev Proxy prints the An error

occurred in a plugin message. When you see any of these messages, you can be sure

that Dev Proxy finished processing the recorded requests.

Example script
Here's an example of a bash script that starts Dev Proxy, waits for it to start, runs tests,
records requests, and stops Dev Proxy:

Bash

# enable job control so that we can send SIGINT to Dev Proxy


set -m

log_file=devproxy.log

echo "Starting Dev Proxy..."

# start Dev Proxy in the background


# log Dev Proxy output to the log file
# log stdout and stderr to the file
./devproxy/devproxy --record > $log_file 2>&1 &

proxy_pid=$!

# wait for init


echo "Waiting for Dev Proxy to start..."
while true; do
if grep -q "Recording" $log_file; then
break
fi
sleep 1
done

# From: https://www.eliostruyf.com/playwright-microsoft-dev-proxy-github-
actions/
# setup certificates
echo "Export the Dev Proxy's Root Certificate"
openssl pkcs12 -in ~/.config/dev-proxy/rootCert.pfx -clcerts -nokeys -out
dev-proxy-ca.crt -passin pass:""

echo "Installing certutil..."


sudo apt install libnss3-tools

echo "Adding certificate to the NSS database for Chromium..."


mkdir -p $HOME/.pki/nssdb
certutil --empty-password -d $HOME/.pki/nssdb -N
certutil -d sql:$HOME/.pki/nssdb -A -t "CT,," -n dev-proxy-ca.crt -i dev-
proxy-ca.crt
echo "Certificate trusted."

echo "Running Playwright tests..."


npm test

# send SIGINT to Dev Proxy to close it gracefully


echo "Stopping Dev Proxy..."
kill -INT $proxy_pid

echo "Waiting for Dev Proxy to complete..."


while true; do
if grep -q -e "DONE" -e "No requests to process" -e "An error occurred in
a plugin" $log_file; then
break
fi
sleep 1
done

6 Collaborate with us on
GitHub Dev Proxy feedback
The source for this content can Dev Proxy is an open source project.
be found on GitHub, where you Select a link to provide feedback:
can also create and review
issues and pull requests. For  Open a documentation issue
more information, see our
contributor guide.  Provide product feedback
Use Dev Proxy with Azure Pipelines
Article • 06/28/2024

Using Dev Proxy with Azure Pipelines is a great way to test your applications in a
controlled environment. Following these steps, you can use Dev Proxy with your Azure
Pipelines.

7 Note

In this article, we use an Ubuntu agent for Azure Pipelines.

Install Dev Proxy and cache it


Start, by installing Dev Proxy on the agent, but do it only if it isn't already installed. To
install and cache Dev Proxy, add the following steps to your pipeline file:

YAML

variables:
- name: DEV_PROXY_VERSION
value: v0.19.0
- name: DEV_PROXY_CACHE_RESTORED
value: 'false'

steps:
- task: Cache@2
inputs:
key: '"dev-proxy-$(DEV_PROXY_VERSION)"'
path: ./devproxy
cacheHitVar: DEV_PROXY_CACHE_RESTORED
displayName: Cache Dev Proxy

- script: bash -c "$(curl -sL https://aka.ms/devproxy/setup.sh)"


$DEV_PROXY_VERSION
displayName: 'Install Dev Proxy'
condition: ne(variables.DEV_PROXY_CACHE_RESTORED, 'true')

Run the Dev Proxy


When you run Dev Proxy in a CI/CD pipeline, you need to start it from a script, so that
you can close it gracefully. When you have your script ready, invoke it in your pipeline
file:
YAML

- script: bash ./run.sh


displayName: 'Run Dev Proxy'

Upload Dev Proxy logs as artifacts


When you run Dev Proxy in a CI/CD pipeline, you might want to analyze the logs later.
To keep Dev Proxy logs, you can upload them as artifacts:

YAML

- task: PublishPipelineArtifact@1
displayName: Upload Dev Proxy logs
inputs:
targetPath: $(LOG_FILE)
artifact: $(LOG_FILE)

Upload Dev Proxy reports


If you're using Dev Proxy to analyze the requests, you might want to upload the reports
as artifacts as well:

YAML

- script: |
mkdir -p $(Build.ArtifactStagingDirectory)/Reports
for file in *Reporter*; do
if [ -f "$file" ]; then
cp "$file" $(Build.ArtifactStagingDirectory)/Reports
fi
done
displayName: 'Copy reports to artifact directory'

- task: PublishPipelineArtifact@1
displayName: Upload Dev Proxy reports
inputs:
targetPath: '$(Build.ArtifactStagingDirectory)/Reports'
artifact: 'Reports'

Example pipeline file


Here's an example of a pipeline file that installs Dev Proxy, runs it, and uploads the logs
and reports as artifacts:
YAML

trigger:
- main
- dev

pool:
vmImage: ubuntu-latest

variables:
- name: LOG_FILE
value: devproxy.log
- name: DEV_PROXY_VERSION
value: v0.19.0
- name: DEV_PROXY_CACHE_RESTORED
value: 'false'
- name: PLAYWRIGHT_CACHE_RESTORED
value: 'false'

steps:

- task: UseNode@1
inputs:
version: '20.x'
displayName: 'Install Node.js'

- script: npm ci
displayName: 'Install dependencies'

#################################
# Cache + install of Playwright #
#################################
- script: |
PLAYWRIGHT_VERSION=$(npm ls @playwright/test | grep @playwright | sed
's/.*@//')
echo "Playwright's Version: $PLAYWRIGHT_VERSION"
echo "##vso[task.setvariable
variable=PLAYWRIGHT_VERSION]$PLAYWRIGHT_VERSION"
displayName: Store Playwright's Version

- task: Cache@2
inputs:
key: '"playwright-ubuntu-$(PLAYWRIGHT_VERSION)"'
path: '$(HOME)/.cache/ms-playwright'
cacheHitVar: PLAYWRIGHT_CACHE_RESTORED
displayName: Cache Playwright Browsers for Playwright's Version

- script: npx playwright install --with-deps


condition: ne(variables['PLAYWRIGHT_CACHE_RESTORED'], 'true')
displayName: 'Install Playwright Browsers'

################################
# Cache + install of Dev Proxy #
################################
- task: Cache@2
inputs:
key: '"dev-proxy-$(DEV_PROXY_VERSION)"'
path: ./devproxy
cacheHitVar: DEV_PROXY_CACHE_RESTORED
displayName: Cache Dev Proxy

- script: bash -c "$(curl -sL https://aka.ms/devproxy/setup.sh)"


$DEV_PROXY_VERSION
displayName: 'Install Dev Proxy'
condition: ne(variables.DEV_PROXY_CACHE_RESTORED, 'true')

- script: bash ./run.sh


displayName: 'Run Dev Proxy'

- task: PublishPipelineArtifact@1
displayName: Upload Dev Proxy logs
inputs:
targetPath: $(LOG_FILE)
artifact: $(LOG_FILE)

- script: |
mkdir -p $(Build.ArtifactStagingDirectory)/Reports
for file in *Reporter*; do
if [ -f "$file" ]; then
cp "$file" $(Build.ArtifactStagingDirectory)/Reports
fi
done
displayName: 'Copy reports to artifact directory'

- task: PublishPipelineArtifact@1
displayName: Upload Dev Proxy reports
inputs:
targetPath: '$(Build.ArtifactStagingDirectory)/Reports'
artifact: 'Reports'

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
be found on GitHub, where you Select a link to provide feedback:
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
Use Dev Proxy with GitHub Actions
Article • 06/25/2024

Using Dev Proxy with GitHub Actions is a great way to test your applications in a
controlled environment. If you want to use Dev Proxy with your GitHub Actions
workflow, you need to include a couple of steps in your workflow file to be able to trust
the Dev Proxy certificate.

7 Note

In this example, we will make use of an Ubuntu runner for GitHub Actions.

Install Dev Proxy and cache it


Start, by installing Dev Proxy on the runner, but do it only if it isn't already installed. To
install and cache Dev Proxy, add the following steps to your workflow file:

YAML

- name: Cache Dev Proxy


id: cache-devproxy
uses: actions/cache@v4
with:
path: ./devproxy
key: devproxy-linux-v0.18.0

- name: Install Dev Proxy


if: steps.cache-devproxy.outputs.cache-hit != 'true'
run: bash -c "$(curl -sL https://aka.ms/devproxy/setup.sh)" -- v0.18.0

Run the Dev Proxy


When you run Dev Proxy in a CI/CD pipeline, you need to start it from a script, so that
you can close it gracefully. When you have your script ready, invoke it in your workflow
file:

YAML

- name: Run Dev Proxy


run: /bin/bash run-dev-proxy.sh
Upload Dev Proxy logs as artifacts
When you run Dev Proxy in a CI/CD pipeline, you might want to analyze the logs later.
To keep Dev Proxy logs, you can upload them as artifacts:

YAML

- name: Upload Dev Proxy logs


uses: actions/upload-artifact@v4
with:
name: ${{ env.LOG_FILE }}
path: ${{ env.LOG_FILE }}

Upload Dev Proxy reports


If you're using Dev Proxy to analyze the requests, you might want to upload the reports
as artifacts as well:

YAML

- name: Upload Dev Proxy reports


uses: actions/upload-artifact@v4
with:
name: Reports
path: ./*Reporter*

Write job summary


To make it easier to understand the results of your workflow, you can write a summary
at the end of your job. Typically, you use the MarkdownReporter for generating job
summaries, because it produces output in Markdown format:

YAML

- name: Write summary


run: |
cat YourPlugin_MarkdownReporter.md >> $GITHUB_STEP_SUMMARY

Example workflow file


Here's an example of a complete workflow file that uses Dev Proxy (based on an
[example by Elio Struyf ):
YAML

name: Test app using Dev Proxy

on:
push:
branches:
- main
- dev
workflow_dispatch:

jobs:
test:
name: Test app using Dev Proxy
timeout-minutes: 60
runs-on: ubuntu-latest
env:
LOG_FILE: devproxy.log
DEVPROXY_VERSION: v0.18.0
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
cache: "npm"

- name: Install dependencies


run: npm ci

#################################
# Cache + install of Playwright #
#################################
- name: Store Playwright's Version
run: |
PLAYWRIGHT_VERSION=$(npm ls @playwright/test | grep @playwright |
sed 's/.*@//')
echo "Playwright's Version: $PLAYWRIGHT_VERSION"
echo "PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION" >> $GITHUB_ENV

- name: Cache Playwright Browsers for Playwright's Version


id: cache-playwright
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-ubuntu-${{ env.PLAYWRIGHT_VERSION }}

- name: Install Playwright Browsers


if: steps.cache-playwright.outputs.cache-hit != 'true'
run: npx playwright install --with-deps

################################
# Cache + install of Dev Proxy #
################################
- name: Cache Dev Proxy
id: cache-devproxy
uses: actions/cache@v4
with:
path: ./devproxy
key: devproxy-ubuntu-${{ env.DEVPROXY_VERSION }}

- name: Install Dev Proxy


if: steps.cache-devproxy.outputs.cache-hit != 'true'
run: bash -c "$(curl -sL https://aka.ms/devproxy/setup.sh)" -- ${{
env.DEVPROXY_VERSION }}

- name: Run Dev Proxy


run: /bin/bash run.sh

- name: Upload Dev Proxy logs


uses: actions/upload-artifact@v4
with:
name: ${{ env.LOG_FILE }}
path: ${{ env.LOG_FILE }}

# only when using a reporting plugin with the Markdown reporter


- name: Upload Dev Proxy reports
uses: actions/upload-artifact@v4
with:
name: Reports
path: ./*Reporter*

# only when using a reporting plugin with the Markdown reporter


- name: Write summary
run: |
cat SomePlugin_MarkdownReporter.md >> $GITHUB_STEP_SUMMARY

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
Dev Proxy doesn't intercept requests
Article • 02/04/2025

Dev Proxy is running, but no requests are intercepted. Several reasons can cause this
issue.

Dev Proxy isn't registered as a system proxy


If Dev Proxy isn't registered as a system proxy, it doesn't intercept any requests, unless
you explicitly configure your app to use it. If you want Dev Proxy to intercept all
requests, make sure it's registered as a system proxy.

After starting Dev Proxy, check your system proxy settings to verify that Dev Proxy is
registered as a system proxy.

If you start Dev Proxy and it's not registered as a system proxy, verify its settings. In the
command line, open the Dev Proxy config file by running devproxy config . Verify, that
the file doesn't contain the asSystemProxy: false setting.

URL isn't included in the configuration


If the URL you're trying to intercept isn't included in the configuration, Dev Proxy
doesn't intercept requests to it. Make sure the URL is included in the urlsToWatch
section of the configuration file.

Learn more about configuring URLs to watch.

No requests are intercepted


Dev Proxy is running, is registered as a system proxy, the URL is included in the
configuration, but it still doesn't intercept requests. Some apps don't automatically pick
up system proxy settings, which can cause this issue. In this case, you need to configure
your app to use Dev Proxy explicitly.

See the section on using Dev Proxy with different apps in this documentation.
Why are random errors not thrown
when using mocks
Article • 01/18/2024

You might find that when trying to use random errors and mocks, proxy isn't returning
random errors. One of the reasons could be the incorrect order of plugins in the
devproxyrc configuration.

Proxy executes plugins in the order they're defined in the configuration. In this case,
mocks are executed before random errors so if you have a mock defined for a URL, the
request never reaches the random error plugin.

If you want both random errors and mocks, change the order of plugins to:

JSON

{
"plugins": [
// [...] trimmed for brevity
{
"name": "GenericRandomErrorPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "genericRandomErrorPlugin"
},
{
"name": "MockResponsePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "mocksPlugin"
}
// [...] trimmed for brevity
],
// [...] trimmed for brevity
}

This way random errors are handled first, and any request that proxy doesn't randomly
fail, is compared against mocks.

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review  Open a documentation issue
issues and pull requests. For
more information, see our  Provide product feedback
contributor guide.
Why do all requests fail with gateway
timeout
Article • 01/18/2024

If you're running the proxy for the first time, it can happen that the network access
configuration didn't propagate timely and the proxy started without access to your
network.

Close the proxy by pressing Ctrl + C in proxy's window and restart the proxy and it
should be working as intended.

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
Why do I keep getting 429 responses
Article • 01/18/2024

If you have the failure rate at 100% , then no request can ever succeed.

If you configure a lower failure rate, then a previously throttled request is passed to the
API provided the Retry-After time period elapses.

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
Why is my internet connection not
working after using the proxy
Article • 11/20/2023

If you terminate the Dev Proxy process, the proxy doesn't unregister itself and your
network connection on your machine is blocked.

To restore network connection, start the proxy and close it by pressing Ctrl + C .
Closing proxy this way gracefully closes the proxy unregistering it on your machine and
restoring the regular network connection.
Why is proxy not intercepting requests
from my .NET 4.8 app
Article • 04/08/2024

To use devproxy with .NET 4.8, you need to configure it as proxy with the WinHTTP API .

Use the netsh command to configure the proxy. (run as admin):

Console

netsh winhttp set proxy proxy-


server="http=localhost:8000;https=localhost:8000"

When you're done, you can reset the WinHTTP settings by using:

Console

netsh winhttp reset proxy

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
Why is proxy not mocking my binary
response
Article • 04/08/2024

The dollar sign has special meaning in some shells and might need to be escaped.

In PowerShell, use a backtick:

PowerShell

Invoke-WebRequest -Method GET -Uri


"https://graph.microsoft.com/v1.0/users/id/photo/`$value" -Proxy
http://localhost:8000

In bash, wrap the URL in double quotes and add a backslash:

Console

curl -ikx http://localhost:8000


"https://graph.microsoft.com/v1.0/users/id/photo/\$value"

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
Why is the proxy saying that an option
is unknown
Article • 01/18/2024

Dev Proxy uses a plugin architecture, as such, proxy features can be added, removed,
enabled or disabled through changing the configuration in the devproxyrc.json file.

Some plugins provide command line options. When the plugin is disabled, the proxy
isn't able to interpret the command line options that the plugin provides.

By default, we ship with many plugins that are configured but disabled.

For example, the ExecutionSummaryPlugin records proxy activity and exposes command
line options, such as --summary-file-path . As the plugin is disabled, the --summary-
file-path option is an unknown option and so the proxy returns an error.

To enable a plugin and make its options available for use, open the devproxyrc.json file,
locate the plugin and set enabled to true .

JSON

{
"name": "ExecutionSummaryPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "executionSummaryPlugin"
}

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
The type initializer for
'Microsoft.Data.Sqlite.SqliteConnection'
threw an exception
Article • 04/08/2024

After starting the proxy, you see the following error:

text

The type initializer for 'Microsoft.Data.Sqlite.SqliteConnection' threw an


exception.

This error happens when macOS doesn't consider the libe_sqlite3.dylib file an
executable.

Open the dev-proxy installation folder in a command prompt and execute chmod +x
libe_sqlite3.dylib .

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
SQLite Error 11: 'database disk image is
malformed'
Article • 04/08/2024

After starting Dev Proxy, you see the following error:

text

SQLite Error 11: 'database disk image is malformed'.

This error happens when Dev Proxy failed updating the SQLite database previously.

Dev Proxy uses a SQLite database for the GraphSelectGuidancePlugin to know which
Microsoft Graph endpoints support the $select parameter. Dev Proxy automatically
updates the database when it starts using Microsoft Graph API metadata. Updating the
database can fail, for example, because you close Dev Proxy when it's writing
information to the database. It corrupts the database and you start seeing the
aforementioned error.

To fix the error, rebuild the database using the msgraphdb command by running:

Console

devproxy msgraphdb

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
Create a custom plugin
Article • 02/05/2025

In this article, you learn how to create a custom plugin for the Dev Proxy. By creating
plugins for Dev Proxy, you can extend its functionality and add custom features to fit
your needs.

Prerequisites
Before you start creating a custom plugin, make sure you have the following
prerequisites:

.NET Core SDK


The latest version of the Dev Proxy Abstractions DLL, which you can find on the
Dev Proxy GitHub releases page

Create a new plugin


Follow the next steps to create a new project:

1. Create a new class library project using the dotnet new classlib command.

Console

dotnet new classlib -n MyCustomPlugin

2. Open the newly created project in Visual Studio Code.

Console

code MyCustomPlugin

3. Add the Dev Proxy Abstractions DLL ( dev-proxy-abstractions.dll ) to the project


folder.

4. Add the dev-proxy-abstractions.dll as a reference to your project


DevProxyCustomPlugin.csproj file.

XML
<ItemGroup>
<Reference Include="dev-proxy-abstractions">
<HintPath>.\dev-proxy-abstractions.dll</HintPath>
<Private>false</Private>
<ExcludeAssets>runtime</ExcludeAssets>
</Reference>
</ItemGroup>

5. Add the NuGet packages required for your project.

Console

dotnet add package Microsoft.Extensions.Configuration


dotnet add package Microsoft.Extensions.Configuration.Binder
dotnet add package Microsoft.Extensions.Logging.Abstractions
dotnet add package Unobtanium.Web.Proxy

6. Exclude the dependency DLLs from the build output by adding a ExcludeAssets
tag per PackageReference in the DevProxyCustomPlugin.csproj file.

XML

<ExcludeAssets>runtime</ExcludeAssets>

7. Create a new class that implements the BaseProxyPlugin interface.

C#

using Microsoft.DevProxy.Abstractions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;

namespace MyCustomPlugin;

public class CatchApiCalls(IPluginEvents pluginEvents, IProxyContext


context, ILogger logger, ISet<UrlToWatch> UrlsToWatch,
IConfigurationSection? configSection = null) :
BaseProxyPlugin(pluginEvents, context, logger, UrlsToWatch,
configSection)
{
public override string Name => nameof(CatchApiCalls);

public override async Task RegisterAsync()


{
await base.RegisterAsync();

PluginEvents.BeforeRequest += BeforeRequestAsync;
}
private Task BeforeRequestAsync(object sender, ProxyRequestArgs e)
{
if (UrlsToWatch is null ||
!e.HasRequestUrlMatch(UrlsToWatch))
{
// No match for the URL, so we don't need to do anything
Logger.LogRequest("URL not matched", MessageType.Skipped, new
LoggingContext(e.Session));
return Task.CompletedTask;
}

var headers = e.Session.HttpClient.Request.Headers;


var header = headers.Where(h => h.Name ==
"Authorization").FirstOrDefault();
if (header is null)
{
Logger.LogRequest($"Does not contain the Authorization header",
MessageType.Warning, new LoggingContext(e.Session));
return Task.CompletedTask;
}

return Task.CompletedTask;
}
}

8. Build your project.

Console

dotnet build

Use your custom plugin


To use your custom plugin, you need to add it to the Dev Proxy configuration file:

1. Add the new plugin configuration in the devproxyrc.json file.

JSON

{
"plugins": [{
"name": "CatchApiCalls",
"enabled": true,
"pluginPath": "./bin/Debug/net8.0/MyCustomPlugin.dll",
}]
}

2. Run the Dev Proxy.


Console

devproxy

The example plugin checks all matching URLs for the required Authorization header. If
the header isn't present, it shows a warning message.

Adding custom configuration to your plugin


(optional)
You can extend your plugin's logic by adding custom configuration:

1. Add a new _configuration object and bind it in the Register method.

C#

using Microsoft.DevProxy.Abstractions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;

namespace MyCustomPlugin;

public class CatchApiCallsConfiguration


{
public string? RequiredHeader { get; set; }
}

public class CatchApiCalls(IPluginEvents pluginEvents, IProxyContext


context, ILogger logger, ISet<UrlToWatch> UrlsToWatch,
IConfigurationSection? configSection = null) :
BaseProxyPlugin(pluginEvents, context, logger, UrlsToWatch,
configSection)
{
public override string Name => nameof(CatchApiCalls);

// Define you custom configuration


private readonly CatchApiCallsConfiguration _configuration = new();

public override async Task RegisterAsync()


{
await base.RegisterAsync();

// Bind your plugin configuration


configSection?.Bind(_configuration);

// Register your event handlers


PluginEvents.BeforeRequest += BeforeRequestAsync;
}
private Task BeforeRequestAsync(object sender, ProxyRequestArgs e)
{
if (UrlsToWatch is null ||
!e.HasRequestUrlMatch(UrlsToWatch))
{
// No match for the URL, so we don't need to do anything
Logger.LogRequest("URL not matched", MessageType.Skipped, new
LoggingContext(e.Session));
return Task.CompletedTask;
}

// Start using your custom configuration


var requiredHeader = _configuration?.RequiredHeader ??
string.Empty;
if (string.IsNullOrEmpty(requiredHeader))
{
// Required header is not set, so we don't need to do anything
Logger.LogRequest("Required header not set", MessageType.Skipped,
new LoggingContext(e.Session));
return Task.CompletedTask;
}

var headers = e.Session.HttpClient.Request.Headers;


var header = headers.Where(h => h.Name ==
requiredHeader).FirstOrDefault();
if (header is null)
{
Logger.LogRequest($"Does not contain the {requiredHeader}
header", MessageType.Warning, new LoggingContext(e.Session));
return Task.CompletedTask;
}

return Task.CompletedTask;
}
}

2. Build your project.

Console

dotnet build

3. Update your devproxyrc.json file to include the new configuration.

JSON

{
"plugins": [{
"name": "CatchApiCalls",
"enabled": true,
"pluginPath": "./bin/Debug/net8.0/MyCustomPlugin.dll",
"configSection": "catchApiCalls"
}],
"catchApiCalls": {
"requiredHeader": "Authorization" // Example configuration
}
}

4. Run the Dev Proxy.

Console

devproxy
Get help and support
Article • 02/05/2025

The fastest and easiest way of getting in touch with us is via the GitHub Issues list.

Create a new issue in the repo and provide as much information as you can for us to
be able to respond timely to your issue.

If something went wrong or you're seeing unexpected results, raise a new issue and
provide a minimal reproducible example . Having a clearly described error helps us
respond and solve your issue faster.
Uninstall
Article • 06/18/2024

If you want to remove Dev Proxy from your machine, follow these steps.

1. Uninstall Dev Proxy by running in the command prompt: winget uninstall


Microsoft.DevProxy

2. Remove the Dev Proxy certificate from your machine.


a. Open Start Menu .
b. In the search box, Enter Manage user certificates .
c. To open the Certificates dialog box, select the result in the list.
d. In the tree view, expand the Personal folder and select the Certificates child
folder.
e. Remove the Dev Proxy CA certificate by selecting and pressing the Delete key
on your keyboard, or right select and in the menu select Delete .
f. To confirm the deletion, Select Yes .

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
What is a proxy?
Article • 04/24/2025

A proxy is an intermediary server that sits between a client (such as your application) and a
destination server (such as a back-end API). When your application sends a request, the proxy
receives it first. The proxy can then forward the request to the target server, modify it, block it,
or return a response directly.

In short, a proxy acts on behalf of either the client or the server to mediate communication.

How a proxy works


Proxies operate at the HTTP level (or other application protocols) by receiving incoming
requests and taking one or more of the following actions:

Forwarding the request to the target server and then relaying the response back to the
client.
Modifying headers, URLs, or payloads before forwarding.
Intercepting and responding to the request locally without contacting the target server.
Rejecting the request based on rules or access policies.

From the perspective of the client, it's simply sending a request to a URL. The proxy handles
everything else behind the scenes. The pattern is client to proxy to target server.

This pattern introduces a layer of control and abstraction that you can use to improve security,
observability, performance, and testability.

Types of proxies
There are different types of proxies. Each one is suited to specific roles in system architecture.

Forward proxy
A forward proxy sits in front of the client. When your application makes a request, it goes
through the proxy, which decides whether and how to forward it. Forward proxies are
commonly used to:

Control access to external resources.


Anonymize client traffic.
Log outgoing traffic for monitoring.
Apply content filtering or transformation.
Reverse proxy
A reverse proxy sits in front of the server. Clients are unaware of the underlying back-end
infrastructure. The reverse proxy receives incoming requests and forwards them to one of
several back-end servers. Reverse proxies are commonly used to:

Load balance traffic across multiple services.


Serve cached responses to reduce back-end load.
Terminate TLS/SSL connections.
Hide internal service details from the public internet.

Transparent proxy
A transparent proxy intercepts traffic without the client being explicitly configured to use it.
This type is used in corporate or internet service provider environments to enforce policies or
monitor usage.

Why proxies matter to application developers


Often infrastructure or network teams manage proxies. However, proxies directly affect
application behavior, especially in development and testing environments. Here are some
practical ways they affect your day-to-day work.

Debugging and observability


Proxies can capture and inspect HTTP traffic. Tools like Dev Proxy, Fiddler, Proxyman, Charles
Proxy, or mitmproxy act as local forward proxies. You can run your application through them to
analyze requests and responses, spot errors, and verify headers or authentication tokens.

API gateway and routing


In many production systems, traffic to your application's back end is routed through an API
gateway or reverse proxy, such as NGINX, or a cloud-native service like Azure API
Management. These proxies handle routing, authentication, rate limiting, and more.

When you design your API or building distributed services, you must understand how proxies
affect headers (such as X-Forwarded-For ), time-outs, and request size limits.

CORS and local development


During local development, especially in web applications, you might encounter cross-origin
resource sharing (CORS) restrictions when you call APIs from the browser. A development
proxy can forward your requests to the target API while it rewrites headers to bypass CORS
limitations. Common examples of developer tools that rewrite CORS requests are vite ,
webpack-dev-server , or custom proxy middleware in frameworks like Express or ASP.NET Core.

Service virtualization and testing


Proxies can simulate back-end APIs. This capability is useful when the real service is
unavailable, unstable, or expensive to use during testing. By intercepting and mocking
responses, you can test application behavior under different scenarios such as time-outs,
errors, or malformed data.

Tools like Dev Proxy or custom proxy implementations are commonly used for this purpose in
integration and end-to-end tests.

Authentication and security


Proxies are often the front line of defense in securing applications. They can enforce access
controls, inject authentication headers, or terminate TLS/SSL connections. As a developer, it's
important to be aware of how your application behaves when it sits behind a proxy and how to
access headers that carry authentication or identity information.

Common headers and proxy considerations


When a request passes through a proxy, certain headers are added or modified to preserve
important metadata. For example:

X-Forwarded-For : Indicates the original IP address of the client.

X-Forwarded-Proto : Indicates the original protocol (HTTP or HTTPS).


X-Forwarded-Host : Indicates the original host requested by the client.

When your application runs behind a reverse proxy, make sure that your framework or
platform is configured to trust and interpret these headers correctly.

Dev Proxy as a forward proxy for development and


testing
Dev Proxy is a forward proxy that you can use to intercept and modify requests from your
application to any target server. With Dev Proxy, you can:
See how your app responds to API errors.
Verify how your app handles API rate limits.
See how your app handles slow APIs.
Quickly stand up mock APIs without writing a line of code.
Improve your app with contextual guidance on how you use APIs.

Next step
Get started
What is caching?
Article • 04/24/2025

Caching is a technique that's used to improve the performance and efficiency of an application
by temporarily storing frequently accessed data in a location that's faster to retrieve than its
original source. Caching helps you reduce the time it takes to retrieve data and reduce the load
on the original data source.

You can use several types of caching in your application:

Memory caching: Store data in the application's memory, which is faster to access than
retrieving it from a database or external API. You typically use memory caching for data
that's frequently accessed and changes infrequently.
Disk caching: Store data on the local disk of the server or client, which can be faster to
access than retrieving it from a remote location. You typically use disk caching for larger
data sets that might not fit in memory, or for data that you need to persist between
application restarts.
Distributed caching: Store data in a distributed cache, which is a cache that's shared
between multiple servers or instances of an application. Distributed caching is useful for
applications that are deployed across multiple servers because it allows data to be shared
and accessed quickly between instances.
Content delivery network (CDN) caching: Store data on a CDN, which is a network of
servers that are distributed around the world. CDN caching is helpful when you need to
deliver static content, such as images or videos. It allows the content to be served from a
location that's closer to the user, which reduces latency and improves performance.

When you implement caching in an application, consider the trade-offs between performance
and data consistency. Caching can improve performance by reducing the time it takes to
retrieve data, but it can also introduce the risk of serving stale or outdated data. To mitigate
this risk, consider using techniques such as cache invalidation or cache expiration. Cache
invalidation removes data from the cache when it's updated. Cache expiration sets a time-to-
live limit for cached data, after which it's automatically removed from the cache.

Caching is a powerful technique that can help you improve the performance and efficiency of
your application by temporarily storing frequently accessed data in a faster location. After you
implement these techniques, verify that your application handles caching properly by using
Dev Proxy.

Next step
Verify caching by using the CachingGuidancePlugin
What is throttling?
Article • 04/24/2025

Throttling is a technique that cloud APIs use to limit the number of requests that can be made
in a specific period of time. Throttling ensures that the API remains available and responsive to
all users. It also prevents any single user from consuming too many resources.

You can experience throttling in several ways. One common way is by using HTTP status codes.
For example, when a user exceeds the allowed number of requests, the API might return a 429
Too Many Requests status code. This response indicates that the user issued too many requests

in a specific period of time and should slow down.

In addition to status codes, some APIs might also provide more information in the response
headers or body. For example, they might use the Retry-After header to indicate how long
the user should wait before making another request.

You need to be aware of the throttling limits of the APIs that you use, and know how to handle
throttling errors appropriately in your apps. Throttling helps you ensure that your apps remain
responsive and reliable, even when the API is under heavy load.

Next step
Test that my application handles throttling properly
How to handle API throttling
Article • 04/24/2025

API throttling is a common challenge that developers face when they build applications that
rely on cloud APIs. Here are some common techniques that you can use to handle API
throttling in your applications:

Use rate limiting. If the API that you use supports rate limiting, use rate limiting
information sent by the API in your application to ensure that your application doesn't
exceed the API's rate limits.
Handle Retry-After headers. Some APIs send a Retry-After header in their response
when a request is throttled. If you get throttled, and the API sends a response with a
Retry-After header, wait for the specified time before you send another request.

Implement exponential backoff. If the API that you use doesn't send a Retry-After
header, implement an exponential backoff algorithm. After each failed request, wait twice
as long before you try again. Waiting longer helps you reduce the load on the API and
increases the chances of your subsequent requests being successful.
Cache previously received data. Cache responses from the API, especially for requests
that are likely to return the same data. Caching helps you reduce the number of calls
made to the API and stay within the rate limits.
Use queue requests. Implement a queue for outgoing API requests to manage the
request rate and ensure that the API's rate limits aren't exceeded.
Optimize API calls. Optimize your API calls by fetching only the data that you need and
using batch requests if supported by the API. Optimizing helps you reduce the number of
resources required to process the response and stay within the rate limits.

By implementing these techniques, you can make your application more resilient to API
throttling and ensure a smoother interaction with external services.

After you implement these techniques in your application, test if it handles throttling properly.

Next step
Test that my application handles throttling properly
What is rate limiting?
Article • 04/24/2025

Rate limiting is a control mechanism that cloud APIs use to regulate the number of requests
that a user can make in a specific time. Cloud API producers use rate limiting to ensure that the
flow of requests doesn't overwhelm the service. Rate limiting sets a cap on the speed and
volume of API calls. Rate limits are typically defined in terms of requests per period of time.

Why cloud APIs use rate limiting


Prevent overload. Rate limiting ensures that the API server remains stable and responsive
by preventing any single user or service from flooding it with too many requests.
Ensure fair usage. Rate limiting enforces fair usage policies by ensuring that no single
user monopolizes the API resources. Rate limiting allows equitable access to all users.
Increase security. Rate limiting helps in mitigating Distributed Denial of Service attacks
and other abusive behaviors by restricting the number of requests from potentially
malicious sources.
Manage costs. For cloud service providers, rate limiting helps in managing operational
costs by preventing unpredictable or excessive use of resources.
Maintain quality of service. Rate limiting ensures a consistent quality of service for all
users by preventing traffic spikes.

How you experience rate limiting in your apps


When you build apps that integrate cloud APIs, check their documentation to verify if they
support rate limiting. If they do, you receive RateLimit-... or X-RateLimit-... response
headers with information about the rate limits. You can use this information in your application
to ensure that you don't exceed the API's rate limits. For example, the RateLimit-Remaining
header indicates the number of requests remaining in the current window. If you receive a
response with this header set to 0, you know that you reached the rate limit and should wait
for the next window before you send another request. The RateLimit-Reset header indicates
the time when the rate limit resets. Some APIs send the RateLimit-... headers only after you
reach a threshold. An example is when you have 10% of the requests remaining.

When you exceed the rate limit, the API throttles your requests and returns an HTTP 429 Too
Many Requests status code. Some APIs might also send a Retry-After header to indicate how

long you should wait before you send another request.

To avoid throttling and ensure that your application remains responsive, implement rate
limiting in your application. Depending on your technology stack, different libraries can help
you handle rate limiting in your application. After you implement rate limiting in your
application, test to see if it handles rate limiting properly.

Next step
Test that my application handles rate limiting properly
How to handle rate limiting
Article • 04/24/2025

Rate limiting is a common technique used by API providers to manage the number of requests
that can be made to their service in a specific time period. API providers use rate limiting to
ensure that their service remains available and responsive to all users, and to prevent abuse or
overuse of the service.

When you use cloud APIs in your application, you should understand their rate limits. The
following techniques can help you handle rate limiting in your applications:

Understand rate limits. Check the documentation of the API that you use to understand
its rate limits. Rate limits might depend on the API provider or the service plan that you
use. For example, some APIs might have different rate limits for free and paid plans.
Use rate limiting information. APIs that use rate limits typically communicate the current
rate limits in the response headers. For example, the RateLimit-Remaining header
indicates the number of requests that remain in the current window. If you receive a
response with this header set to 0, you know that you reached the rate limit and should
wait for the next window before you send another request. The RateLimit-Reset header
indicates the time when the rate limit resets. Some APIs send the RateLimit-... headers
only after you reach a threshold. An example is when you have 10% of the requests
remaining.
Optimize API usage. Some services assign different costs to different requests based on
their complexity. For example, some APIs might charge more for requests that return
more data. To reduce the cost of your application, optimize your API usage by fetching
only the data that you need. Use batch requests if the API supports them. They help you
reduce the number of resources required to process the response and stay within the rate
limits.
Implement a local rate limiter. Implement a rate limiter within the application itself to
limit the number of requests that can be made to the API in a specific time period. You
can do it by using techniques such as token bucket or leaky bucket algorithms, which
allow the application to make many requests per time period. Any more requests are
queued or discarded.
Avoid exceeding rate limits. When you exceed rate limits, the API throttles all subsequent
requests that typically return an HTTP 429 Too Many Requests status code. Typically,
throttling affects the throughput of your application more than rate limiting. Use the
information exposed in rate limit response headers to stay within the rate limits and avoid
throttling.

By using these techniques, you can build applications that are resilient to rate limiting and can
continue to function even when the API is under heavy load.
Next step
Test that my application handles rate limiting properly
How to implement rate limiting in Azure
API Management
Article • 04/24/2025

By using rate limiting, you can limit the number of API calls that a user or service can make in a
specific time period. Rate limiting helps you ensure fair usage and prevents any single user or
service from monopolizing the API resources. Azure API Management provides a convenient
way to implement rate limiting for your APIs.

Why use Azure API Management?


Azure API Management is a powerful and versatile cloud service that helps organizations
publish APIs to external, partner, and internal developers. It provides tools for securing,
managing, and scaling API calls. One of its features is controlling rate limiting, which is useful
for maintaining the health and reliability of your APIs.

Configure rate limiting in Azure API Management


Azure API Management uses policies to enforce rate limiting. You can define these policies at
different scopes: global, product, or API-specific. This flexibility allows you to tailor rate limiting
according to your API's requirements and usage patterns.

Before you start implementing rate limiting, decide on the rate limits. The limits you set
depend on your API's capacity and the traffic that you expect. Common limits are set as the
number of calls per second, minute, or hour. For instance, you might allow 1,000 calls per
minute per user.

To define rate limits on your API in Azure API Management, use the rate-limit or rate-limit-by-
key policies. The rate-limit policy sets a limit across all users. The rate-limit-by-key policy
allows limits per identified key (like a subscription or a user ID).

Here's an example of a policy that limits the calls to 1,000 per minute.

XML

<policies>
<inbound>
<base />
<rate-limit calls="1000" renewal-period="60" />
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>

When you exceed the specified number of calls, Azure API Management sends a 429 Too Many
Requests status code, along with the retry-after response header and a message that

indicates when you can try again.

text

HTTP/1.1 429 Too Many Requests


content-type: application/json
retry-after: 60

{
"statusCode": 429,
"message": "Rate limit is exceeded. Try again in 60 seconds."
}

Expose rate limit information on response headers


By default, Azure API Management doesn't expose rate limit information on response headers.
Not communicating rate limits makes it difficult for apps to avoid exceeding the limit and
getting throttled. To expose rate limit information, extend the rate-limit policy with the
remaining-calls-header-name and total-calls-header-name properties.

XML

<policies>
<inbound>
<base />
<rate-limit calls="1000" renewal-period="60" remaining-calls-header-
name="ratelimit-remaining" total-calls-header-name="ratelimit-limit" />
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>

When you call your API now, each response includes the ratelimit-remaining and ratelimit-
limit headers. The headers communicate how many more calls the API can handle before it

exceeds the limit.

Summary
Implementing rate limiting in Azure API Management helps you create robust and scalable
APIs. By using rate limiting, you can ensure that your API serves your users reliably and
efficiently. The key is to find the right balance. If a rate limit is too strict, you might hinder
usability. If a rate limit is too lenient, you risk overwhelming your API. With careful planning
and continuous monitoring, you can achieve this balance and maintain a healthy API
environment.

Next step
Test that my application handles rate limiting properly
What is chaos testing?
Article • 04/24/2025

Chaos testing is a technique that's used to test the resilience of software systems by
introducing unexpected failures or disruptions. Chaos testing is also known as chaos
engineering. The goal of chaos testing is to identify weaknesses and improve your app's
resilience.

Chaos testing is based on the idea that systems fail in unexpected ways. Traditional testing
methods often fall short in uncovering these unexpected failure modes. When you use chaos
testing, you simulate real-world scenarios, such as server crashes, network latency, or resource
exhaustion. Simulating these behaviors helps to expose hidden issues and weaknesses that
might not be evident under normal testing conditions.

Here are some key points to keep in mind about chaos testing:

Be proactive. Instead of waiting for failures to happen, chaos testing proactively


introduces failures to see how the system responds. Chaos testing allows you to identify
and fix issues before they become major problems.
Gain insights. The goal of chaos testing isn't to break the system but to learn from it. By
introducing failures, you can gain valuable insights into how the system behaves under
stress and use that information to improve it.
Promote a team effort. Chaos testing is most effective when you do it collaboratively.
You want input from developers, testers, operations, and other stakeholders. By working
together, you can identify the most important areas to test and ensure that everyone is
informed.
Start small and build up. When you first start with chaos testing, it's a good idea to start
small and gradually increase the complexity of your tests. Starting small helps you build
confidence and develop a better understanding of how the system behaves under
different conditions.

In summary, chaos testing is a powerful technique that can help you improve the resilience of
your apps. By proactively introducing failures and learning from them, you can identify and fix
issues before they become major problems.

Dev Proxy makes it easy to introduce failures into your apps and test how they respond. You
can use Dev Proxy to simulate API failures in any type of app, on any technology stack, without
changing your code.

Next step
Test my app with random errors
How to work with large datasets
Article • 04/24/2025

When you work with APIs that expose large datasets, use techniques such as pagination,
filtering, sorting, and caching to optimize API requests for performance.

Use pagination
Different APIs have different pagination options. Read the API's documentation to understand
how to use pagination correctly. Some common pagination options include:

Specify the number of records to retrieve per page.


Use a cursor to retrieve the next set of records.
Use a continuation token to retrieve the next page of data.

The @odata.nextLink property contains a URL that the API returns when there are more results
available than can be returned in a single response. You can use this property to retrieve the
next page of results by making another API call to the URL specified in the @odata.nextLink
property. You can continue to retrieve more pages of results until the @odata.nextLink
property is no longer present in the response, which indicates that you retrieved all results.

You can use Dev Proxy to see if your application uses pagination correctly.

Set a reasonable page size


When you specify the number of records to retrieve per page, choose a reasonable page size. If
the page size is too small, you have to make many API requests to retrieve all the data. This
process is slow and inefficient. If the page size is too large, you put too much load on the API.
This strain can lead to time-outs or errors. Choose a page size that balances the number of API
requests with the amount of data retrieved per request.

Cache paginated data


If you're retrieving paginated data that doesn't change frequently, consider caching the data.
Caching reduces the number of API requests and improves the performance of your
application. Implement a cache invalidation strategy to ensure that the data in the cache is up
to date.

By following these tips, you can work with APIs that expose large datasets and optimize your
API requests for performance.
Next step
Check if your application uses pagination correctly
What is an OpenAPI spec?
Article • 04/24/2025

OpenAPI Specification, formerly known as Swagger, describes various aspects of an API. An


OpenAPI specification (spec) describes the API's endpoints, parameters, and responses.
OpenAPI specs are written in YAML or JSON and are used by tools to generate documentation,
test cases, and client libraries. By having an OpenAPI spec, API builders can ensure that their
API is accurately described, more accessible, and easier to integrate across a wide range of
applications and services.

Here's why you should consider having an OpenAPI spec for your API:

Document an API in a standardized way. Document an API specification in a consistent


and human-readable format.
Generate a client SDK. Use tools such as Kiota to automate generating of client libraries
in various programming languages.
Create a mock API. Create mock servers based on the API specification, which helps you
during the early stages of development when the actual API isn't yet implemented.
Improve collaboration. Provide different teams (front end, back end, QA) with a clear
understanding of the API's capabilities and limitations, which helps new team members to
get caught up quickly.
Simplify testing and validation. Automate validation of API requests and responses
against the specification, which makes it easier to identify discrepancies.
Integrate with API management tools. Easily integrate, deploy, and monitor your APIs
with many API management tools and gateways, such as Azure API Center and Azure API
Management.
Simplify API gateway configuration. Use OpenAPI specs to configure API gateways and
automate tasks such as routing, transformations, and cross-origin resource sharing
settings.

By using OpenAPI specs, you can create APIs that are well-designed and consistently
documented. They're also more maintainable and easier to use both internally and by external
consumers.

If you don't have an OpenAPI spec for your API, you can use Dev Proxy to generate one from
the intercepted requests and responses.

Next step
Generate an OpenAPI spec
How to debug Microsoft Graph API calls
Article • 04/24/2025

You might build an application that uses Microsoft Graph APIs to connect to Microsoft 365 and
discover that the API isn't working as you expected. How do you debug it? This article shares
some recommendations for debugging Microsoft Graph API calls.

Check for known issues


Before you start debugging, check if the issue that you're facing is a known issue with the
Microsoft Graph API. For more information, see the Microsoft Graph known issues website.

Check the changelog


If you're using the Microsoft Graph beta endpoint, check the Microsoft Graph changelog for
any changes that might affect your application. The changelog contains information about new
features, changes, and fixes in the Microsoft Graph API. It also contains information about
breaking changes that might affect your application.

Check the documentation


When the API isn't working as expected, check its documentation. It might contain information
that can help you understand the issue that you're facing. For example, the documentation
might contain information about known limitations, specific requirements, or other
considerations.

Check the throttling limits


Check the throttling limits for the API that you're using. If you exceed the throttling limits, the
API might return an HTTP 429 (Too Many Requests) status code. If you get throttled, handle it
properly in your application.

Handle expected errors


Microsoft Graph uses standard HTTP status codes to communicate its errors. For more
information about status codes that Microsoft Graph APIs returns, see Microsoft Graph error
responses and resource types.
Generate and log a unique client-request-id
On every request to Microsoft Graph, generate a unique GUID, send it in the client-request-
id HTTP request header, and log it in your application's logs. This information helps you to

track and correlate requests and responses when you debug issues. It also helps Microsoft
Support to diagnose the issue if you need to report it.

Log the request ID and date from the HTTP


response headers
Always log the request ID and date from the HTTP response headers. Together with the
client-request-id header, they're required when you report issues in Microsoft Q&A or to

Microsoft Support. Without these headers, diagnosing the issue is difficult.

Use Dev Proxy to see if your application adds the client-request-id HTTP request header to
the requests that it sends to Microsoft Graph.

Next step
Check if my app uses the client-request-id header
Can I use Microsoft Graph beta endpoints
in production?
Article • 04/24/2025

Microsoft Graph beta endpoint is a preview version of the API that you can use to test and
experiment with new features before they're released to the general public. Using the
Microsoft Graph beta endpoint is a great way to take advantage of the latest innovations. The
beta endpoint isn't intended for use in production environments.

One of the main risks of using beta Microsoft Graph endpoints in production apps is that the
APIs and functionalities available in the beta endpoint are subject to change. As a result,
features and APIs that you rely on in your app might be modified or removed without notice.
Their removal might cause disruptions or breaking changes to your app.

The beta endpoint also might not have the same level of support, reliability, or performance as
the v1.0 endpoint. It can unexpectedly change or be unavailable, have slower response times,
or cause other issues that can affect the user experience of your app.

For these reasons, we strongly recommend that developers use the v1.0 endpoint when they
build production apps. The v1.0 endpoint provides a stable and reliable API that Microsoft
supports. By using the v1.0 endpoint, you can ensure that your app is built on a solid
foundation and that your users have the best possible experience.

Use Dev Proxy to see if your application uses the Microsoft Graph beta endpoint.

Next step
Check if my app uses Microsoft Graph beta endpoints
Recommended search APIs for Microsoft
365
Article • 04/24/2025

In the past, if you wanted to search lists and files, you used the OneDrive and SharePoint
search APIs. In October 2023, Microsoft released guidance on how to search in Microsoft
365 . This guidance recommends that you use the Microsoft Graph search API instead of the
OneDrive and SharePoint search APIs. The OneDrive and SharePoint search APIs are still
available, but Microsoft no longer updates them.

To use the recommended search APIs, you need to update your code to use the Microsoft
Graph search API. Start by identifying if your application uses the OneDrive and SharePoint
search APIs. Look for the following requests:

graph.microsoft.com/{version}/drives/{drive-id}/root/search(q='{search-text}')

graph.microsoft.com/{version}/groups/{group-id}/drive/root/search(q='{search-text}')
graph.microsoft.com/{version}/me/drive/root/search(q='{search-text}')

graph.microsoft.com/{version}/sites/{site-id}/drive/root/search(q='{search-text}')

graph.microsoft.com/{version}/users/{user-id}/drive/root/search(q='{search-text}')
graph.microsoft.com/{version}/sites?search={query}

 Tip

Use the Dev Proxy ODSPSearchGuidancePlugin to identify if your application uses the
OneDrive and SharePoint search APIs.

Update each of these requests to use the Microsoft Search API instead. For examples of how to
translate the different requests, see the search guidance .

Next step
Use the ODSPSearchGuidancePlugin
Use Dev Proxy for API design: build
better APIs from the start
Article • 10/28/2024

Designing APIs is crucial to building reliable, scalable applications, but the process can
be challenging without the right tools. Dev Proxy simplifies the API design process,
enabling you to prototype, simulate, and refine your API before you fully implement it.
With Dev Proxy, you can create, test, and document your API early, ensuring it meets the
needs of your app and users from day one.

Why use Dev Proxy for API design?


Dev Proxy empowers developers to simulate API behavior in real-time, even before the
actual API exists. By using Dev Proxy during the design phase, you can:

Prototype faster: Build your app while designing the API, eliminating delays, and
reducing bottlenecks in development.
Ensure reliability: Identify potential issues with API interactions, such as response
handling and edge cases, early in the design process.
Collaborate seamlessly: Share API mocks and specifications with your team,
enabling clear communication and alignment throughout development.
Accelerate iteration: Quickly adapt your API design based on feedback and
testing, improving agility and reducing costly changes later in the process.

Key Dev Proxy features for API design


Dev Proxy offers a range of features to support API design, including:

Mock API responses


Simulate API responses instantly without the need for a live backend. Test how your app
behaves with different response scenarios, giving you the flexibility to build and refine
both the API and the app simultaneously.

Generate OpenAPI specifications


Automatically generate API documentation, ensuring that your API design is clearly
defined and easy to share with stakeholders. Having API documentation helps you
create well-structured, self-explanatory APIs that are easy to adopt.

Simulate CRUD APIs


Design and test Create-, Read-, Update-, and Delete APIs without a functioning
backend. Verify how your API handles functionality from the ground up without
guessing and waiting for the backend to be ready.

Record and export Dev Proxy activity


Track all API interactions and export them for review, ensuring that your API design
evolves based on real-world app usage. Use this data to refine and optimize your API
before it goes live.

Start designing better APIs today


Dev Proxy makes API design faster, smarter, and more efficient. With its powerful
simulation and mock capabilities, you can design robust APIs that meet your app's
needs right from the start. Whether you're building new APIs or refining existing ones,
Dev Proxy provides the tools to get it right the first time.

Ready to give it a try?


Download Dev Proxy and start designing better APIs today. Explore the features, create
your first mock API, and experience how Dev Proxy can streamline your development
process.

Discover our how-to guides and unlock the full potential of Dev Proxy. Let's build the
future of APIs together!

Download Dev Proxy


Use Dev Proxy for API testing: validate
API performance and reliability with
confidence
Article • 10/28/2024

Testing APIs is essential to building resilient, high-performing applications that can


handle real-world scenarios and unexpected conditions. Dev Proxy equips you with the
tools to test your API's behavior, providing insights into its performance, error handling,
and overall robustness before it's live. With Dev Proxy, you can thoroughly evaluate your
API's reliability, identify potential issues, and optimize performance.

Why Use Dev Proxy for API testing?


Dev Proxy allows you to simulate real-world API conditions and errors, ensuring that
your API performs consistently under various scenarios. By using Dev Proxy for API
testing, you can:

Identify vulnerabilities early: Detect and address weaknesses before they reach
your users by simulating diverse conditions like network delays, rate limiting, and
error responses.
Improve app reliability: Test how your application handles different API responses,
helping you create apps that respond smoothly to unexpected issues.
Streamline testing: Simplify your testing process by running comprehensive API
simulations without a dedicated backend, saving time and reducing testing
dependencies.

Key Dev Proxy features for API testing


Dev Proxy offers a range of features to support API testing, enabling you to validate
your API's performance, reliability, and error handling under various conditions.

Simulate API error responses


Test how your application manages various error responses (for example, 400 and 500
HTTP errors), enabling you to design effective error-handling logic and failover
mechanisms.
Simulate API throttling (rate-limiting)
Simulate rate-limit responses to ensure your app gracefully handles throttling and retry
scenarios, minimizing disruptions to the user experience.

Simulate slow APIs


Introduce network latency to see how your app performs under slow API conditions,
helping you design smoother user interfaces and efficient timeout handling.

Mock API responses


Easily create mock responses for testing, allowing you to test the API's expected
behavior in a controlled environment and simulate different response types and
structures.

Start testing your APIs with Dev Proxy


With Dev Proxy, you can make API testing a seamless part of your development process,
ensuring your APIs perform consistently and predictably under various conditions. From
error simulations to request inspection, Dev Proxy provides the capabilities to deliver a
robust, well-tested API.

Ready to start?
Download Dev Proxy and put your API to the test. With our how-to guides, you're up
and running in minutes, empowering you to confidently deliver APIs that excel under
real-world conditions. Try Dev Proxy today and build better APIs!

Download Dev Proxy


Use Dev Proxy for API publishing:
publish reliable, production-ready APIs
Article • 10/28/2024

Making your API accessible to consumers is a critical step, but API publishing is about
more than just going live. To drive adoption and ensure high-quality user experiences,
your API needs to be optimized, fully documented, and secure. Dev Proxy streamlines
the API publishing process, helping you ensure your API is ready for production use and
easy to consume by developers.

Why use Dev Proxy for API publishing?


Dev Proxy provides essential tools to make publishing APIs seamless, robust, and
optimized for consumption. With Dev Proxy, you can:

Ensure production-readiness: Validate that your API endpoints are correctly


configured for live environments, reducing risks associated with development-only
settings.
Optimize API security: Detect and enforce minimal permissions, ensuring that your
API provides just the right level of access and safeguards against potential misuse.
Streamline API adoption: Automatically generate OpenAPI specifications and
configuration presets, making your API accessible, clear, and ready for developers
to integrate quickly.
Enhance performance tracking: Record API activity to analyze usage patterns,
optimize performance, and address issues proactively for a better end-user
experience.

Key Dev Proxy features for API publishing


Dev Proxy offers a range of features to support API publishing, enabling you to ensure
your API is production-ready, secure, and optimized for consumption.

Generate OpenAPI specifications


Automatically generate comprehensive API documentation, providing consumers with
clear guidance on how to use your API and reducing integration time and effort.

Check production-level API calls


Ensure that all API calls adhere to production standards, preventing accidental use of
development endpoints and configurations that might affect security or performance.

Detect minimal API permissions


Analyze and set minimal required permissions, enforcing security best practices and
ensuring that consumers have only the necessary level of access.

Simulate behaviors with plugin configuration


Customize and control API behavior under various conditions, enabling you to refine
your API's performance, rate limits, and error handling.

Ready to publish your API with confidence?


Dev Proxy equips you with the tools to seamlessly publish production-ready APIs that
are optimized, secure, and easy for developers to adopt. Whether you're preparing for
your API's initial release or optimizing an existing API for broader use, Dev Proxy
provides a streamlined, reliable path to successful API publishing.

Get started today


Download Dev Proxy to make your API publishing process faster and more effective.
Explore our how-to guides and learn how to publish APIs that meet production
standards from the start.

Download Dev Proxy


Use Dev Proxy for API versioning:
seamlessly support API evolution
Article • 10/28/2024

As your API grows and evolves, managing different versions efficiently is essential to
maintain compatibility, guide adoption of the latest features, and ensure secure and
reliable API usage. Dev Proxy simplifies API versioning, providing tools that help you
support current and deprecated versions, enforce production-ready standards, and keep
your API documentation up to date for all consumers.

Why use Dev Proxy for API Versioning?


Dev Proxy enables you to version APIs effectively, helping ensure that your users can
adopt new capabilities smoothly and that outdated versions are securely managed. With
Dev Proxy, you can:

Guide users to supported versions: Automatically document changes for each


version, helping developers stay up to date with the latest features and
requirements.
Enforce production standards: Ensure that only supported, stable API versions are
available in production environments, reducing risks associated with using
deprecated versions.
Optimize security across versions: Monitor permissions across versions, making it
easy to keep your API secure as it evolves.

Key Dev Proxy features for API versioning


Dev Proxy offers a range of features to support API versioning, enabling you to manage
versions effectively, enforce standards, and support seamless transitions to the latest
versions.

Generate OpenAPI specifications


Automatically generate documentation for each API version, providing clear,
comprehensive details to developers on using the latest features and making version
migration straightforward.

Check production-level API calls


Validate that production systems only call stable, supported API versions, preventing the
risk of using deprecated versions and maintaining consistent standards across
environments.

Detect minimal API permissions


Analyze and apply minimal required permissions for each version, optimizing security
and ensuring that every API version enforces the necessary level of access.

Start managing API versions with confidence


Dev Proxy provides the tools you need to maintain, secure, and evolve your APIs over
time, ensuring that consumers always have access to the latest features with minimal
disruption. Whether you're managing new releases or phasing out older versions, Dev
Proxy helps you stay in control of your API lifecycle.

Get started today


Download Dev Proxy and take control of your API versioning process. With our how-to
guides, you're ready to manage versioning efficiently, enforce standards, and support
seamless transitions to the latest versions. Try Dev Proxy today and build a sustainable,
forward-compatible API ecosystem!

Download Dev Proxy


Technical reference for Dev Proxy
Article • 04/15/2025

This section contains technical reference for Dev Proxy plugins and configuration options.

Plugins
List of plugins that work with any API.

ノ Expand table

Name Description

AuthPlugin Simulates authentication and authorization using API keys or


OAuth2.

DevToolsPlugin Exposes Dev Proxy messages, and information about intercepted


requests and responses in Chrome DevTools.

CachingGuidancePlugin Shows a warning when Dev Proxy intercepted the same request
within the specified period of time.

CrudApiPlugin Simulates a CRUD API with an in-memory data store.

ExecutionSummaryPlugin Generates a summary report of the requests that pass through the
proxy.

GenericRandomErrorPlugin Fails requests with a random selected error from file containing
mocked errors.

HttpFileGeneratorPlugin Generates HTTP file from the intercepted requests and responses.

LatencyPlugin Delays responses by a random number of milliseconds from the


configured range.

MinimalCsomPermissionsPlugin Detects the minimal permissions needed to call the recorded


SharePoint Client-Side Object Model (CSOM) API requests.

MinimalPermissionsPlugin Checks if the app uses minimal permissions to call APIs. Uses API
information from the specified local folder.

MinimalPermissionsGuidancePlugin Compares the permissions used in the JWT token sent to APIs
against the minimum required scopes needed for requests that
proxy recorded and shows the difference.

MockGeneratorPlugin Generates Dev Proxy mocks based on the intercepted requests.

MockRequestPlugin Allows you to issue web requests using Dev Proxy.


Name Description

MockResponsePlugin Simulates responses.

ODataPagingGuidancePlugin Shows a warning when proxy intercepts an OData paging request


using a URL that hasn't been previously returned in one of the
intercepted responses.

OpenAIMockResponsePlugin Simulates responses from Azure OpenAI and OpenAI using a local
language model.

OpenApiSpecGeneratorPlugin Generates OpenAPI spec from the intercepted requests and


responses.

RateLimitingPlugin Simulates rate-limit behaviors.

RetryAfterPlugin Simulates the Retry-After header sent by an API after throttling a


request.

RewritePlugin Rewrites requests.

TypeSpecGeneratorPlugin Generates TypeSpec files from the intercepted requests and


responses.

UrlDiscoveryPlugin Creates a list of URLs that the proxy has intercepted.

Azure API Center plugins


List of plugins that work with Azure API Center.

ノ Expand table

Name Description

ApiCenterMinimalPermissionsPlugin Checks if the app uses minimal permissions to call APIs. Uses API
information from the specified Azure API Center instance.

ApiCenterOnboardingPlugin Checks if the APIs used in an app are registered in the specified
Azure API Center instance.

ApiCenterProductionVersionPlugin Checks if the APIs used in an app are production version of the
APIs registered in the specified Azure API Center instance.

Microsoft Entra plugins


List of plugins that work with Microsoft Entra API.
ノ Expand table

Name Description

EntraMockResponsePlugin Mocks responses to Microsoft Entra.

Microsoft Graph plugins


List of plugins that work with Microsoft Graph API.

ノ Expand table

Name Description

GraphBetaSupportGuidancePlugin Shows a warning when proxy detects a request to Microsoft


Graph beta endpoint.

GraphClientRequestIdGuidancePlugin Shows a tip when a request to Microsoft Graph API doesn't


include the client-request-id header.

GraphConnectorGuidancePlugin Shows contextual guidance for working with Microsoft Graph


connectors.

GraphConnectorNotificationPlugin Simulates the notification when enabling or disabling a


Microsoft Graph connector in Teams Admin Center (TAC).
Validates requests for creating and deleting the external
connection.

GraphMinimalPermissionsPlugin Returns a list of the minimal permissions required for


Microsoft Graph requests that proxy recorded.

GraphMinimalPermissionsGuidancePlugin Compares the permissions used in the JWT token sent to


Microsoft Graph against the minimum required scopes
needed for requests that proxy recorded and shows the
difference.

GraphMockResponsePlugin Mocks responses to Microsoft Graph APIs.

GraphRandomErrorPlugin Fails requests made to Microsoft Graph with random errors.

GraphSdkGuidancePlugin Shows a tip when proxy intercepts a request to Microsoft


Graph that hasn't been issued by a Microsoft Graph SDK.

GraphSelectGuidancePlugin Shows a warning when proxy intercepts a request to


Microsoft Graph APIs that doesn't include the $select query
string parameter.

ODSPSearchGuidancePlugin Shows a warning when Dev Proxy detects a request to


OneDrive and SharePoint search APIs.
Reporters
List of reporters that generate reports in different formats.

ノ Expand table

Name Description

JsonReporter Generates reports in JSON format.

MarkdownReporter Generates reports in Markdown format.

PlainTextReporter Generates reports in plain-text format.

Configuration
Reference of Dev Proxy configuration options.

ノ Expand table

Name Description

devproxyrc Configuration file for Dev Proxy.

Proxy API API for interacting with Dev Proxy programmatically.

Proxy settings Configuration options for proxy settings.


Console output text labels
Article • 05/24/2024

Dev Proxy uses the following text labels in the console output.

ノ Expand table

Label Description

req Proxy intercepted a request

api Proxy ignored a request and passed it through

oops Proxy simulated an API error

warn Proxy returned a performance warning

mock Proxy mocked the response

log Normal log entry

fail Request failed

tip Proxy provided developer guidance

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
devproxyrc
Article • 04/30/2025

Default Dev Proxy configuration file.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/rc.schema.json",
"plugins": [
{
"name": "RetryAfterPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
},
{
"name": "GenericRandomErrorPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "genericRandomErrorPlugin"
}
],
"urlsToWatch": [
"https://jsonplaceholder.typicode.com/*"
],
"genericRandomErrorPlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/genericrandomerrorplugin.schema.json",
"errorsFile": "devproxy-errors.json",
"rate": 50,
},
"logLevel": "information",
"newVersionNotification": "stable",
"showSkipMessages": true,
"showTimestamps": true,
"validateSchemas": true
}
Does Dev Proxy upload any data to
Microsoft
Article • 12/15/2023

No, it doesn't.

While the proxy intercepts all network traffic on your machine, it doesn't upload any
data to Microsoft.
Resolve relative paths
Article • 04/08/2024

All file paths used in configuration files ( devproxyrc.json ) are relative to the location of
the configuration file.

In the below example, the pluginPath is relative to the configuration file. The default
devproxyrc.json configuration file is located in the same location where the plugins

folder exists.

JSON

{
"name": "GraphSelectGuidancePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"urlsToWatch": [
"https://graph.microsoft.com/v1.0/*",
...
]
}

Let's say you start the proxy from a different directory, such as from the location of a
project you're working in.

If an devproxyrc.json configuration file exists in the current directory, then the file path
resolution is relative to this file. If not, the proxy falls back to the default
devproxyrc.json file.

Using a configuration file that isn't located in the proxy installation directory requires
you to ensure that plugin paths are resolved correctly.

Use the ~appFolder token in the file paths to ensure that the path is prepended with the
absolute path to the proxy installation directory.

JSON

{
"name": "GraphSelectGuidancePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"urlsToWatch": [
"https://graph.microsoft.com/v1.0/*",
...
]
}

The ~appFolder token can be used in any path used by the proxy.

Let's say you want to load a preset configuration, you can use the ~appFolder token in
the path to reference the configuration file located in the proxy installation directory.

Console

devproxy --config-file ~appFolder/presets/microsoft-graph.json

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
Plugin architecture
Article • 02/05/2025

A plugin is a .NET class registered with Dev Proxy that introduces a specific Dev Proxy
behavior. A plugin can offer real-time guidance about API usage, simulate API behavior,
analyze multiple API requests, or produce a report. Dev Proxy has three types of plugins:

intercepting plugins that intercept requests and responses and can analyze and
modify them
reporting plugins that run on requests recorded by Dev Proxy
reporters that generate reports based on the data collected by reporting plugins

You register plugins in the devproxyrc.json file. The file contains a list of plugins to load
and their configuration.

Dev Proxy comes with a collection of plugins and you can create custom plugins to
extend Dev Proxy functionality to match your needs.

When Dev Proxy starts, it loads plugins enabled in its configuration file. Depending
which plugins you enable, Dev Proxy can provide guidance, simulate API behavior, or
analyze API requests. Following sections explain how the different types of plugins work.

Intercepting plugins
When Dev Proxy intercepts a request matching one of the URLs in the urlsToWatch
array, it invokes each intercepting plugin in the order they're listed in the configuration
file. Each intercepting plugin inherits from the BaseProxyPlugin class, and can
subscribe to the following events:

BeforeRequest - raised when Dev Proxy intercepts a request


BeforeResponse - raised after Dev Proxy receives a response from the server

AfterResponse - raised after Dev Proxy sends the response to the client

For each of these events, plugins can define an event handler. In the handler, the plugin
can analyze the request and response, and modify it if needed. It can also output
guidance messages. To see what's possible, see the code of plugins provided with Dev
Proxy .

Reporting plugins
Dev Proxy allows you to record API requests and responses. You typically use recording
to report on API usage or analyze multiple API requests. Reporting plugins inherit from
the BaseReportingPlugin class, and register an event handler with the
AfterRecordingStop event.

When you stop recording, Dev Proxy raises the AfterRecordingStop event, passing the
list of recorded requests and responses as an argument to the registered event handlers.
Reporting plugins can then analyze the recorded data and generate a report object. A
report object is an arbitrary object defined by the reporting plugin. Reporting plugins
store the reports by calling the StoreReport method.

) Important

Reporting plugins generate report objects, which Dev Proxy stores in memory. To
convert these report objects into user-readable reports, you must enable one or
more reporters in the Dev Proxy configuration file.

Reporters
Dev Proxy uses reporters to convert report objects generated by reporting plugins into
user-readable reports. For example, the MarkdownReporter converts a report object into
a Markdown file. Reporters are special plugins that inherit from the BaseReporter
class. They implement the GetReport method, which takes as argument a report
created by a reporting plugin and converts it into a string. This string is then saved on
disk following the PluginName_ReporterName.ReporterExtension pattern, for example:
ApiCenterOnboardingPlugin_MarkdownReporter.md .

) Important

Because reporters depend on the report objects generated by reporting plugins,


you must enable the reporting plugins in the Dev Proxy configuration file after
reporting plugins. If you enable them before reporting plugins, reporters won't
have any data to report on.
Proxy settings
Article • 03/12/2025

Dev Proxy comes with several settings that you can use to control how the proxy should
run.

You can configure these settings by setting them in the devproxyrc.json file, located in
the proxy installation folder, or by setting them at run time through command line
options.

The following table describes the settings.

ノ Expand table

Setting Description Command- Allowed values Default


line option value

apiPort The port for n/a integer 8897


the Dev
Proxy API to
listen on

asSystemProxy Whether to --as-system- true , false true


register Dev proxy
Proxy as the
system proxy
on startup.
When set to
true
requires
installCert
to be, set to
true

filterByHeaders Only n/a {"filterByHeaders": [ { n/a


intercept "name": "value" } ] } . Value
requests with can be empty to include
specific requests with the specified
headers header no matter its value.

installCert Whether to --install- true , false true


install the cert
root
certificate

ipAddress The IP --ip-address IPv4 address 127.0.0.1


address for <ipAddress>
Setting Description Command- Allowed values Default
line option value

the proxy to
bind to

languageModel Settings for n/a See the language model n/a


the language section for more information.
model

logLevel Level of --log-level trace , debug , information , information


messages to <loglevel> warning , error
log

newVersionNotification Whether to n/a none , stable , beta stable


notify about
new versions

noFirstRun Skip the first --no-first- n/a n/a


run run
experience
(don't trust
certificate on
macOS)

port The port for -p, --port integer 8000


the proxy <port>
server to
listen on

rate The -f, --failure- 0..100 50


percentage rate
of chance <failurerate>
that proxy
fails a
request. Set
to 0 to pass
all requests
to APIs, and
to 100 to fail
all requests.

record Use this --record n/a n/a


option to
record all
request logs

showSkipMessages Whether to n/a true , false true


show log
messages
when Dev
Setting Description Command- Allowed values Default
line option value

Proxy skips
running a
plugin.

timeout Automatically -t, --timeout integer n/a


stop proxy <seconds>
after a period
of inactivity

urlsToWatch List of URLs -u, --urls-to- Absolute URL (can contain See
that proxy watch wildcards) for example, devproxyrc
should <urlsToWatch> "https://api.contoso.com/*" file
intercept

validateSchemas Whether to n/a true , false true


validate
configuration
against the
specified
schema

watchPids The IDs of --watch-pids integer n/a


processes to <pids>
watch for
requests

watchProcessNames The names of --watch- string n/a


processes to process-names
watch for <processNames>
requests
Proxy API
Article • 04/02/2025

Dev Proxy comes with a web API that allows you to interact with the proxy
programmatically. The API is available on the port specified in the proxy settings.

Swagger
The API is documented using Swagger. You can access the Swagger UI by navigating to
http://localhost:<apiPort>/swagger in your browser.

Operations
The following list shows available API operations.

GET /proxy

Returns an instance of ProxyInfo with information about the currently running Dev
Proxy instance.

Example: Get information about the currently running Dev Proxy


instance
Request:

HTTP

GET http://localhost:8897/proxy

Response:

text

200 OK

{
"recording": false,
"configFile": "/Users/user/dev-proxy/devproxyrc.json"
}
POST /proxy

Controls the currently running Dev Proxy instance.

Example: start recording


Request:

HTTP

POST http://localhost:8897/proxy
content-type: application/json

{
"recording": true
}

Response:

text

200 OK

{
"recording": true,
"configFile": "/Users/user/dev-proxy/devproxyrc.json"
}

Example: stop recording

Request:

HTTP

POST http://localhost:8897/proxy
content-type: application/json

{
"recording": false
}

Response:

text
200 OK

{
"recording": false,
"configFile": "/Users/user/dev-proxy/devproxyrc.json"
}

POST /proxy/jwtToken

Generates a JSON Web Token (JWT).

Request:

HTTP

POST http://localhost:8897/proxy/jwtToken
Content-Type: application/json

{
"name": "Dev Proxy",
"audiences": [
"https://myserver.com"
],
"issuer": "dev-proxy",
"roles": [
"admin"
],
"scopes": [
"Post.Read",
"Post.Write"
],
"claims": {
"claim1": "value",
"claim2": "value"
},
"validFor": 60
}

7 Note

Registered claims (for example, iss , sub , aud , exp , nbf , iat , jti ) are
automatically added to the token. If you specify any of these claims in the request,
the API ignores the values you provide.

Response:
text

200 OK

{
"token":
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6IkRldiBQcm94eSIsIn
N1YiI6IkRldiBQcm94eSIsImp0aSI6IjkyZjM5YzciLCJzY3AiOlsiUG9zdC5SZWFkIiwiUG9zdC
5Xcml0ZSJdLCJyb2xlcyI6ImFkbWluIiwiY2xhaW0xIjoidmFsdWUiLCJjbGFpbTIiOiJ2YWx1ZS
IsImF1ZCI6Imh0dHBzOi8vbXlzZXJ2ZXIuY29tIiwibmJmIjoxNzI3MTk4MjgyLCJleHAiOjE3Mj
cyMDE4ODIsImlhdCI6MTcyNzE5ODI4MiwiaXNzIjoiZGV2LXByb3h5In0.E_Gj9E58OrAh9uHgc-
TW8DYfq8YHFrhaUTpKA4yXEIg"
}

POST /proxy/mockrequest

Raises a mock request. Equivalent of pressing w in the console where Dev Proxy is
running.

Request:

HTTP

POST http://localhost:8897/proxy/mockrequest

Response:

text

202 Accepted

GET /proxy/rootCertificate?format=crt

Downloads the public key of the root certificate in PEM (Privacy Enhanced Mail) format
that Dev Proxy uses to decrypt HTTPS requests. This API is helpful when you want to
trust the root certificate on your host while running Dev Proxy in a Docker container.

At this moment, the only supported format is crt . The API returns a 400 Bad Request
error if you specify any other format or don't specify a format at all.

Request:

HTTP
GET http://localhost:8897/proxy/rootCertificate?format=crt

Response:

text

content-type: application/x-x509-ca-cert

-----BEGIN CERTIFICATE-----
[base64 encoded certificate]
-----END CERTIFICATE-----

POST /proxy/stopproxy

Gracefully shuts down Dev Proxy.

Request:

HTTP

POST http://localhost:8897/proxy/stopproxy

Response:

text

202 Accepted

Models

ProxyInfo

Information about the currently running Dev Proxy instance.

ノ Expand table

Property Type Description

recording boolean Whether the proxy is currently recording requests

configFile string Path to the configuration file that Dev Proxy is using (read-only)
JwtOptions
Options for generating a JWT token.

ノ Expand table

Property Type Description

name string The name of the user to create the token for

audience string[] The audiences to create the token for

issuer string[] The issuer of the token

roles string[] A role claim to add to the token

scopes string[] A scope claim to add to the token

claims KeyValuePair Claims to add to the token

validFor number The duration (in minutes) for which the token is valid

signingKey string The key to use to sign the token. Must be at least 32 characters
long. If not specified, uses a randomly generated key.

JwtInfo
Information about a JWT token.

ノ Expand table

Property Type Description

token string The JWT token


Keyboard shortcuts
Article • 03/12/2024

The following table describes the keyboard shortcuts available when the proxy is
running.

ノ Expand table

Keyboard Description

ctrl + c Stop the proxy/recording

r Start recording

s Stop recording

c Clear proxy output

w Issue web requests

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
ApiCenterMinimalPermissionsPlugin
Article • 04/30/2025

Checks if the app uses minimal permissions to call APIs. Uses API information from the
specified Azure API Center instance.

Plugin instance definition


JSON

{
"name": "ApiCenterMinimalPermissionsPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "apiCenterMinimalPermissionsPlugin"
}

Configuration example
JSON

{
"apiCenterMinimalPermissionsPlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/apicenterminimalpermissionsplugin.schema.json",
"subscriptionId": "aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e",
"resourceGroupName": "resource-group-name",
"serviceName": "apic-instance",
"workspaceName": "default"
}
}

Configuration properties
ノ Expand table

Property Description Default

resourceGroupName Name of the resource group where the Azure API Center is located. None

serviceName Name of the Azure API Center instance that Dev Proxy should use to None
check if the APIs used in the app are registered.

subscriptionId ID of the Azure subscription where the Azure API Center instance is None
located.

workspace Name of the Azure API Center workspace to use. default

Command line options


None

Remarks
The ApiCenterMinimalPermissionsPlugin plugin checks if the app uses minimal permissions to
call APIs. To check permissions, the plugin uses information about APIs that are registered in
the specified Azure API Center instance.

Connect to Azure API Center


To connect to Azure API Center, the plugin uses Azure credentials (in this order):

Environment
Workload Identity
Managed Identity
Visual Studio
Visual Studio Code
Azure CLI
Azure PowerShell
Azure Developer CLI

If the plugin fails to get an access token to access Azure, it shows an error and Dev Proxy
disables it. Sign in to Azure using either of these tools, and restart Dev Proxy to use the
ApiCenterMinimalPermissionsPlugin plugin.

If you use Dev Proxy in CI/CD pipelines, you can pass values for the subscriptionId ,
resourceGroupName , serviceName , and workspaceName properties as environment variables. To

use environment variables, prepend the name of the value with a @ , for example:

JSON

{
"apiCenterMinimalPermissionsPlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/apicenterminimalpermissionsplugin.schema.json",
"subscriptionId": "@AZURE_SUBSCRIPTION_ID",
"resourceGroupName": "@AZURE_RESOURCE_GROUP_NAME",
"serviceName": "@AZURE_APIC_INSTANCE_NAME",
"workspaceName": "@AZURE_APIC_WORKSPACE_NAME"
}
}

In this example, the ApiCenterMinimalPermissionsPlugin plugin sets subscriptionId ,


resourceGroupName , serviceName , and workspaceName properties to the values of the
AZURE_SUBSCRIPTION_ID , AZURE_RESOURCE_GROUP_NAME , AZURE_APIC_INSTANCE_NAME , and

AZURE_APIC_WORKSPACE_NAME environment variables, respectively.

Define API permissions


The ApiCenterMinimalPermissionsPlugin plugin supports checking OAuth permissions for APIs
secured with OAuth registered in Azure API Center. The plugin computes the minimal
permissions required to call the APIs used in the app using the information from API Center.
Then, the plugin compares the permissions used in the JSON Web Token (JWT) token against
the minimum required scopes needed for the requests that Dev Proxy recorded.

To define permissions for your APIs, include them in the OpenAPI definition of your API. The
following example shows how to define permissions for an API in an OpenAPI definition:

JSON

{
"openapi": "3.0.1",
"info": {
"title": "Northwind API",
"description": "Northwind API",
"version": "v1.0"
},
"servers": [
{
"url": "https://api.northwind.com"
}
],
"components": {
"securitySchemes": {
"OAuth2": {
"type": "oauth2",
"flows": {
"authorizationCode": {
"authorizationUrl":
"https://login.microsoftonline.com/common/oauth2/authorize",
"tokenUrl": "https://login.microsoftonline.com/common/oauth2/token",
"scopes": {
"customer.read": "Grants access to ready customer info",
"customer.readwrite": "Grants access to read and write customer
info"
}
}
}
}
},
"schemas": {
"Customer": {
"type": "object",
// [...] trimmed for brevity
}
}
},
"paths": {
"/customers/{customers-id}": {
"description": "Provides operations to manage a customer",
"get": {
"summary": "Get customer by ID",
"operationId": "getCustomerById",
"security": [
{
"OAuth2": [
"customer.read"
]
},
{
"OAuth2": [
"customer.readwrite"
]
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json; charset=utf-8": {
"schema": {
"$ref": "#/components/schemas/Customer"
}
}
}
}
}
},
"patch": {
"summary": "Update customer by ID",
"operationId": "updateCustomerById",
"security": [
{
"OAuth2": [
"customer.readwrite"
]
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Customer"
}
}
}
},
"responses": {
"204": {
"description": "No Content"
}
}
},
"parameters": [
{
"name": "customers-id",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
]
}
},
"x-ms-generated-by": {
"toolName": "Dev Proxy",
"toolVersion": "0.27.0"
}
}
The relevant part is the securitySchemes section, where you define the OAuth scopes that the
API uses. Then, for each operation, you include the required scopes in the security section.

More information
OpenAPI Authentication and Authorization
OpenAPI specification Security Scheme Object

Next step
How to check if my app is calling APIs with minimal permissions
ApiCenterOnboardingPlugin
Article • 04/30/2025

Checks if the APIs used in an app are registered in the specified Azure API Center instance.

Plugin instance definition


JSON

{
"name": "ApiCenterOnboardingPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "apiCenterOnboardingPlugin"
}

Configuration example
JSON

{
"apiCenterOnboardingPlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/apicenteronboardingplugin.schema.json",
"subscriptionId": "aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e",
"resourceGroupName": "resource-group-name",
"serviceName": "apic-instance",
"workspaceName": "default",
"createApicEntryForNewApis": true
}
}

Configuration properties
ノ Expand table

Property Description Default

createApicEntryForNewApis Set to true to have Dev Proxy create new API entries for the APIs true
that it detected and which aren't yet registered in API Center.
When set to false Dev Proxy only lists the unregistered APIs in
the command prompt.

resourceGroupName Name of the resource group where the Azure API Center is None
located.

serviceName Name of the Azure API Center instance that Dev Proxy should None
use to check if the APIs used in the app are registered.

subscriptionId ID of the Azure subscription where the Azure API Center instance None
is located.

workspace Name of the Azure API Center workspace to use. default

Command line options


None

Remarks
The ApiCenterOnboardingPlugin plugin checks if the APIs used in an app are registered in the
specified Azure API Center instance. If the APIs aren't registered, the plugin can create new API
entries in the API Center instance.

To connect to Azure API Center, the plugin uses Azure credentials (in this order):

Environment
Workload Identity
Managed Identity
Visual Studio
Visual Studio Code
Azure CLI
Azure PowerShell
Azure Developer CLI

If the plugin fails to get an access token to access Azure, it shows an error and Dev Proxy
disables it. Sign in to Azure using either of these tools, and restart Dev Proxy to use the
ApiCenterOnboardingPlugin plugin.

If you use Dev Proxy in CI/CD pipelines, you can pass values for the subscriptionId ,
resourceGroupName , serviceName , and workspaceName properties as environment variables. To

use environment variables, prepend the name of the value with a @ , for example:

JSON

{
"apiCenterOnboardingPlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/apicenteronboardingplugin.schema.json",
"subscriptionId": "@AZURE_SUBSCRIPTION_ID",
"resourceGroupName": "@AZURE_RESOURCE_GROUP_NAME",
"serviceName": "@AZURE_APIC_INSTANCE_NAME",
"workspaceName": "@AZURE_APIC_WORKSPACE_NAME",
"createApicEntryForNewApis": true
}
}

In this example, the ApiCenterOnboardingPlugin plugin sets subscriptionId ,


resourceGroupName , serviceName , and workspaceName properties to the values of the

AZURE_SUBSCRIPTION_ID , AZURE_RESOURCE_GROUP_NAME , AZURE_APIC_INSTANCE_NAME , and


AZURE_APIC_WORKSPACE_NAME environment variables, respectively.

Next step
How to find shadow APIs
ApiCenterProductionVersionPlugin
Article • 04/30/2025

Checks if the APIs used in an app are production version of the APIs registered in the specified
Azure API Center instance.

Plugin instance definition


JSON

{
"name": "ApiCenterProductionVersionPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "apiCenterProductionVersionPlugin"
}

Configuration example
JSON

{
"apiCenterProductionVersionPlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/apicenterproductionversionplugin.schema.json",
"subscriptionId": "aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e",
"resourceGroupName": "resource-group-name",
"serviceName": "apic-instance",
"workspaceName": "default"
}
}

Configuration properties
ノ Expand table

Property Description Default

resourceGroupName Name of the resource group where the Azure API Center is located. None

serviceName Name of the Azure API Center instance that Dev Proxy should use to None
check if the APIs used in the app are registered.

subscriptionId ID of the Azure subscription where the Azure API Center instance is None
located.

workspace Name of the Azure API Center workspace to use. default

Command line options


None

Remarks
The ApiCenterProductionVersionPlugin plugin checks if the APIs used in an app are production
version of the APIs registered in the specified Azure API Center instance. If the APIs match
nonproduction versions, the plugin shows a warning.

To connect to Azure API Center, the plugin uses Azure credentials (in this order):

Environment
Workload Identity
Managed Identity
Visual Studio
Visual Studio Code
Azure CLI
Azure PowerShell
Azure Developer CLI
If the plugin fails to get an access token to access Azure, it shows an error and Dev Proxy
disables it. Sign in to Azure using either of these tools, and restart Dev Proxy to use the
ApiCenterProductionVersionPlugin plugin.

If you use Dev Proxy in CI/CD pipelines, you can pass values for the subscriptionId ,
resourceGroupName , serviceName , and workspaceName properties as environment variables. To

use environment variables, prepend the name of the value with a @ , for example:

JSON

{
"apiCenterProductionVersionPlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/apicenterproductionversionplugin.schema.json",
"subscriptionId": "@AZURE_SUBSCRIPTION_ID",
"resourceGroupName": "@AZURE_RESOURCE_GROUP_NAME",
"serviceName": "@AZURE_APIC_INSTANCE_NAME",
"workspaceName": "@AZURE_APIC_WORKSPACE_NAME"
}
}

In this example, the ApiCenterProductionVersionPlugin plugin sets subscriptionId ,


resourceGroupName , serviceName , and workspaceName properties to the values of the
AZURE_SUBSCRIPTION_ID , AZURE_RESOURCE_GROUP_NAME , AZURE_APIC_INSTANCE_NAME , and

AZURE_APIC_WORKSPACE_NAME environment variables, respectively.

Next step
How to check if my app is using production-level APIs
AuthPlugin
Article • 04/30/2025

Simulates authentication and authorization using API keys or OAuth2.

Plugin instance definition


JSON

{
"name": "AuthPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "auth"
}

Configuration example: API key


JSON

{
"auth": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/authplugin.schema.json",
"type": "apiKey",
"apiKey": {
"parameters": [
{
"in": "header",
"name": "x-api-key"
},
{
"in": "query",
"name": "code"
}
],
"allowedKeys": [
"1234"
]
}
}
}

Configuration example: OAuth2


JSON

{
"auth": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/authplugin.schema.json",
"type": "oauth2",
"oauth2": {
"metadataUrl": "https://login.microsoftonline.com/organizations/v2.0/.well-
known/openid-configuration",
"allowedApplications": [
"00000000-0000-0000-0000-000000000000"
],
"allowedAudiences": [
"00000000-0000-0000-0000-000000000000"
],
"allowedPrincipals": [
"00000000-0000-0000-0000-000000000000"
],
"allowedTenants":[
"00000000-0000-0000-0000-000000000000"
],
"issuer": "https://login.microsoftonline.com/ffffffff-eeee-dddd-cccc-
bbbbbbbbbbb0/v2.0",
"scopes": [
"Posts.Read"
],
"validateLifetime": true,
"validateSigningKey": true
}
}
}

Configuration properties
ノ Expand table

Property Description Required

type Type of authentication and authorization that Dev Proxy should use. Yes
Allowed values: apiKey , oauth2

apiKey Configuration for API key authentication and authorization. Yes, when type is
apiKey

oauth2 Configuration for OAuth2 authentication and authorization. Yes, when type is
oauth2

API key configuration properties

ノ Expand table

Property Description Required

allowedKeys List of allowed API keys. Yes

parameters List of parameters that contain the API key. Yes

Parameter configuration properties

ノ Expand table

Property Description Required

in Where the parameter is expected to be found. Allowed values: header , query , Yes
cookie

name Name of the parameter. Yes

OAuth2 configuration properties

ノ Expand table
Property Description Required

metadataUrl URL to the OpenID Connect metadata document. Yes

allowedApplications List of allowed application IDs. Leave empty to not validate the No
application ( appid or azp claim) for which the token is issued.

allowedAudiences List of allowed audiences. Leave empty to not validate the audience No
( aud claim) for which the token is issued.

allowedPrincipals List of allowed principals. Leave empty to not validate the principal No
( oid claim) for which the token is issued.

allowedTenants List of allowed tenants. Leave empty to not validate the tenant ( tid No
claim) for which the token is issued.

issuer Allowed token issuer. Leave empty to not validate the token issuer. No

roles List of allowed roles. Leave empty to not validate the roles ( roles No
claim) on the token.

scopes List of allowed scopes. Leave empty to not validate the scopes ( scp No
claim) on the token.

validateLifetime Set to false to disable validating the token lifetime. Default true . No

validateSigningKey Set to false to disable validating the token signature. Default true No

Command line options


None
CachingGuidancePlugin
Article • 04/30/2025

Shows a warning when Dev Proxy intercepted the same request within the specified period of
time.

Plugin instance definition


JSON

{
"name": "CachingGuidancePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "cachingGuidance"
}

Configuration example
JSON
{
"cachingGuidance": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/cachingguidanceplugin.schema.json",
"cacheThresholdSeconds": 5
}
}

Configuration properties
ノ Expand table

Property Description Default

cacheThresholdSeconds The number of seconds between the same request that triggers the 5
guidance warning.

Command line options


None
CrudApiPlugin
Article • 04/30/2025

Simulates a CRUD API with an in-memory data store. Sends JSON responses. Supports CORS
for cross-domain usage from client-side applications. Optionally, simulates CRUD APIs secured
with Microsoft Entra.

Plugin instance definition


JSON

{
"name": "CrudApiPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "customersApi"
}

Configuration example
JSON

{
"customersApi": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/crudapiplugin.schema.json",
"apiFile": "customers-api.json"
}
}

Configuration properties
ノ Expand table

Property Description

apiFile Path to the file that contains the definition of the CRUD API

Command line options


None

API file example


Following are several examples of API files that define a CRUD API for information about
customers.

Anonymous CRUD API


Following is an example of an API file that defines an anonymous CRUD API for information
about customers.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/crudapiplugin.apifile.schema.json",
"baseUrl": "https://api.contoso.com/v1/customers",
"dataFile": "customers-data.json",
"actions": [
{
"action": "getAll"
},
{
"action": "getOne",
"url": "/{customer-id}",
"query": "$.[?(@.id == {customer-id})]"
},
{
"action": "create"
},
{
"action": "merge",
"url": "/{customer-id}",
"query": "$.[?(@.id == {customer-id})]"
},
{
"action": "update",
"url": "/{customer-id}",
"query": "$.[?(@.id == {customer-id})]"
},
{
"action": "delete",
"url": "/{customer-id}",
"query": "$.[?(@.id == {customer-id})]"
}
]
}

CRUD API secured with Microsoft Entra using a single scope


Following is an example of an API file that defines a CRUD API for information about customers
secured with Microsoft Entra. All actions are secured with one scope. CrudApiPlugin validates
the token audience, issuer, and the scope.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/crudapiplugin.apifile.schema.json",
"baseUrl": "https://api.contoso.com/v1/customers",
"dataFile": "customers-data.json",
"auth": "entra",
"entraAuthConfig": {
"audience": "https://api.contoso.com",
"issuer": "https://login.microsoftonline.com/contoso.com",
"scopes": ["api://contoso.com/user_impersonation"]
},
"actions": [
{
"action": "getAll"
},
{
"action": "getOne",
"url": "/{customer-id}",
"query": "$.[?(@.id == {customer-id})]"
},
{
"action": "create"
},
{
"action": "merge",
"url": "/{customer-id}",
"query": "$.[?(@.id == {customer-id})]"
},
{
"action": "update",
"url": "/{customer-id}",
"query": "$.[?(@.id == {customer-id})]"
},
{
"action": "delete",
"url": "/{customer-id}",
"query": "$.[?(@.id == {customer-id})]"
}
]
}

CRUD API secured with Microsoft Entra using specific scopes


Following is an example of an API file that defines a CRUD API for information about customers
secured with Microsoft Entra. Actions are secured with specific scopes. CrudApiPlugin validates
the token audience, issuer, and the scope.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/crudapiplugin.apifile.schema.json",
"baseUrl": "https://api.contoso.com/v1/customers",
"dataFile": "customers-data.json",
"auth": "entra",
"entraAuthConfig": {
"audience": "https://api.contoso.com",
"issuer": "https://login.microsoftonline.com/contoso.com"
},
"actions": [
{
"action": "getAll",
"auth": "entra",
"entraAuthConfig": {
"scopes": ["api://contoso.com/customer.read"]
}
},
{
"action": "getOne",
"url": "/{customer-id}",
"query": "$.[?(@.id == {customer-id})]",
"auth": "entra",
"entraAuthConfig": {
"scopes": ["api://contoso.com/customer.read"]
}
},
{
"action": "create",
"auth": "entra",
"entraAuthConfig": {
"scopes": ["api://contoso.com/customer.write"]
}
},
{
"action": "merge",
"url": "/{customer-id}",
"query": "$.[?(@.id == {customer-id})]",
"auth": "entra",
"entraAuthConfig": {
"scopes": ["api://contoso.com/customer.write"]
}
},
{
"action": "update",
"url": "/{customer-id}",
"query": "$.[?(@.id == {customer-id})]",
"auth": "entra",
"entraAuthConfig": {
"scopes": ["api://contoso.com/customer.write"]
}
},
{
"action": "delete",
"url": "/{customer-id}",
"query": "$.[?(@.id == {customer-id})]",
"auth": "entra",
"entraAuthConfig": {
"scopes": ["api://contoso.com/customer.write"]
}
}
]
}

API file properties


ノ Expand table

Property Description Required

actions List of actions that the API supports. Yes

auth Determines if the API is secured or not. Allowed values: No


none , entra . Default none
Property Description Required

baseUrl Base URL where Dev Proxy exposes the URL. Dev Proxy Yes
prepends the base URL to URLs you define in actions.

dataFile Path to the file that contains the data for the API. Yes

entraAuthConfig Configuration for Microsoft Entra authentication. Yes, when you


configure auth to
entra

You can refer to the dataFile using an absolute- or a relative path. Dev Proxy resolves relative
paths relatively to the API definition file.

The dataFile must define a JSON array. The array can be empty or it can contain an initial set
of objects.

EntraAuthConfig properties
When you configure the auth property to entra , you must define the entraAuthConfig
property. If you don't define it, CrudApiPlugin shows a warning and the API is available
anonymously.

You can define entraAuthConfig on the API file and on each API action. When you define it on
the API file, it applies to all actions. When you define it on an action, it overrides the API file
configuration for this specific action.

The entraAuthConfig property has the following properties.

ノ Expand table

Property Description Required Default

audience Specify the valid audience for the token. When specified, No None
CrudApiPlugin compares the audience from the token with
this audience. If they're different, CrudApiPlugin returns a
401 Unauthorized response.

issuer Specify the valid token issuer. When specified, No None


CrudApiPlugin compares the issuer from the token with this
issuer. If they're different, CrudApiPlugin returns a 401
Unauthorized response.

scopes Specify the array of valid scopes. When specified, No None


CrudApiPlugin controls if either of the scopes is present on
Property Description Required Default

the token. If neither of the scopes is present, CrudApiPlugin


returns a 401 Unauthorized response.

roles Specify the array of valid roles. When specified, No None


CrudApiPlugin controls if either of the roles is present on the
token. If neither of the roles is present, CrudApiPlugin
returns a 401 Unauthorized response.

validateLifetime Set to true for the CrudApiPlugin to validate if the token No false
hasn't expired. When CrudApiPlugin detects an expired
token, it returns a 401 Unauthorized response.

validateSigningKey Set to true for the CrudApiPlugin to validate if the token is No false
authentic. When CrudApiPlugin detects a token with an
invalid signature (for example, because you modified the
token manually), it returns a 401 Unauthorized response.

Action properties
Each action in the actions list has the following properties.

ノ Expand table

Property Description Required Default

action Defines how Dev Proxy interacts with the data. Yes None
Possible values: getAll , getOne , getMany ,
create , merge , update , delete .

auth Determines if the action is secured or not. No none


Allowed values: none , entra .

entraAuthConfig Configuration for Microsoft Entra authentication. Yes, when you None
configure auth to
entra

method HTTP method that Dev Proxy uses to expose the No Depends on
action. the action

query Newtonsoft JSONPath query that Dev Proxy No Empty


uses to find the data in the data file.

url URL where Dev Proxy exposes the action on. Dev No Empty
Proxy appends the URL to the base URL.
The URL specified in the url property can contain parameters. You define parameters by
wrapping the parameter name in curly braces, for example, {customer-id} . When routing the
request, Dev Proxy replaces the parameter with the value from the request URL.

You can use the same parameter in the query. For example, if you define the url as
/customers/{customer-id} and the query as $.[?(@.id == {customer-id})] , Dev Proxy replaces

the {customer-id} parameter in the query with the value from the request URL.

) Important

Dev Proxy implements JSONPath in the query property using Newtonsoft.Json. There are
some limitations to using it such as, it supports only single quotes. Before submitting an
issue, be sure to validate your query.

When the plugin can't find the data in the data file using the query, it returns a 404 Not Found
response.

Each action type has a default HTTP method. You can override the default by specifying the
method property. For example, the get action type has a default method of GET . If you want to

use POST instead, specify the method property as POST .

The actions array defined a collection of actions that you want to mock. You can define
multiple actions for the same HTTP method and action type. For example, you can define two
getOne actions, one that retrieves a customer by their ID and the other by their email address.

Be sure to define unique URLs for each action.

Actions

Dev Proxy supports the following actions for CRUD APIs.

ノ Expand table

Action Description Default


method

getAll Returns all items from the data file. GET

getOne Returns a single item from the data file. Fails when the query matches GET
multiple items.

getMany Returns multiple items from the data file. Returns an empty array if the query GET
doesn't match any items.
Action Description Default
method

create Adds a new item to the data collection. POST

merge Merges the data from the request with the data from the data file. PATCH

update Replaces the data in the data file with the data from the request. PUT

delete Deletes the item from the data file. DELETE

When you create a new item using a create action, the plugin doesn't validate its shape and
adds it to the data collection as-is.

Data file example


JSON

[
{
"id": 1,
"name": "Contoso",
"address": "4567 Main St Buffalo, NY 98052"
},
{
"id": 2,
"name": "Fabrikam",
"address": "4567 Main St Buffalo, NY 98052"
}
]

Next step
Simulate a CRUD API
DevToolsPlugin
Article • 04/30/2025

Exposes Dev Proxy messages, and information about intercepted requests and responses in
Chrome DevTools.


Plugin instance definition


JSON

{
"name": "DevToolsPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "devTools"
}

Configuration example
JSON

{
"devTools": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/devtoolsplugin.schema.json",
"preferredBrowser": "Edge"
}
}

Configuration properties
ノ Expand table

Property Description Default

preferredBrowser Which browser to use to launch Dev Tools. Supported values: Edge , Edge
EdgeDev , Chrome

Command line options


None

Known issues

Dev Tools don't open in Microsoft Edge on Windows


You use Dev Proxy on Windows and configure it to use Microsoft Edge to display Dev Tools.
After you start Dev Proxy, it starts the inspector but Dev Tools don't open or they open empty.

To fix this issue:

1. Open Microsoft Edge


2. Go to Settings
3. Open System and performance
4. Disable Startup boost
5. Close all Microsoft Edge windows and processes
6. Start Dev Proxy

Next step
Inspect requests and responses using Chrome DevTools
EntraMockResponsePlugin
Article • 04/08/2024

Mocks responses to Microsoft Entra. Includes all functionality of the


MockResponsePlugin and adds support for mocking auth flow API requests.

When the plugin simulates auth flow API responses, it updates the state and nonce to
match the API request. In the mocked response body, the plugin searches for the
following tokens and replaces them with the actual values from the intercepted API
requests.

ノ Expand table

Token Description

@dynamic.devProxyCertificateChain The certificate chain of the Dev Proxy CA. Dev Proxy
replaces the @dynamic.devProxyCertificateChain token
with the actual certificate chain of the Dev Proxy CA. This
token is useful if you want to validate an access token
issued by Dev Proxy.

@dynamic.devProxyKeyId The key ID of the Dev Proxy CA. Dev Proxy replaces the
@dynamic.devProxyKeyId token with the actual key ID of
the Dev Proxy CA. This token is useful if you want to
validate an access token issued by Dev Proxy.
Token Description

state=@dynamic The state token in the request. Dev Proxy replaces the
@dynamic token with the value of the state query string
parameter

"id_token": Mocked ID token. Dev Proxy removes the @dynamic. token


"@dynamic.eyJ0eXAiOiJKV1QiL..." and updates the value of the nonce claim in the mocked
ID token.

Plugin instance definition


JSON

{
"name": "EntraMockResponsePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "mocksPlugin"
}

Configuration example
See MockResponsePlugin

Configuration properties
See MockResponsePlugin

Command line options


See MockResponsePlugin

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
be found on GitHub, where you Select a link to provide feedback:
can also create and review
 Open a documentation issue
issues and pull requests. For
 Provide product feedback
more information, see our
contributor guide.
ExecutionSummaryPlugin
Article • 04/30/2025

Creates a summary of the requests that pass through the proxy.

 Tip

Use a reporter plugin in your configuration to save the summary to a file.


Plugin instance definition


JSON

{
"name": "ExecutionSummaryPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "executionSummaryPlugin"
}

Configuration example
JSON

{
"executionSummaryPlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/executionsummaryplugin.schema.json",
"groupBy": "url"
}
}
Configuration properties
ノ Expand table

Property Description Default

groupBy How proxy should group the information in the summary. Available options: url , url
messageType

Command line options


ノ Expand table

Name Description Default

--summary-group- How proxy should group the information in the summary. Available url
by options: url , messageType

Next step
Record and export proxy activity
GenericRandomErrorPlugin
Article • 04/30/2025

Fails requests with a random selected error from file containing mocked errors.

Plugin instance definition


JSON

{
"name": "GenericRandomErrorPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "genericRandomErrorPlugin",
"urlsToWatch": [
"https://api.openai.com/*"
]
}

Configuration example
JSON

{
"genericRandomErrorPlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/genericrandomerrorplugin.schema.json",
"errorsFile": "errors.json"
}
}

Configuration properties
ノ Expand table

Property Description Default

errorsFile Path to the file that contains error responses. No


default

rate The percentage of requests to fail with a random error. Value between 50
0 and 100.

retryAfterInSeconds The number of seconds to wait before retrying the request. Included 5
on the Retry-After response header for dynamic throttling.

Command line options


ノ Expand table

Name Description Default

-f, --failure-rate <failure The percentage of requests to fail with a random error. Value 50
rate> between 0 and 100.

Next step
Test my app with random errors
HttpFileGeneratorPlugin
Article • 04/30/2025

Generates HTTP file from the intercepted requests and responses.

Plugin instance definition


JSON

{
"name": "HttpFileGeneratorPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "httpFileGeneratorPlugin"
}

Configuration example
JSON

{
"httpFileGeneratorPlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/httpfilegeneratorplugin.schema.json",
"includeOptionsRequests": false
}
}
Configuration properties
ノ Expand table

Property Description Default

includeOptionsRequests Determines whether to include OPTIONS requests in the generated false


HTTP file

Command line options


None

Remarks
When the plugin generates the HTTP file, it extracts authorization information such as bearer
tokens and API keys from request headers and query string parameters. It replaces the actual
values with placeholders and stores them in variables for easier management.

For example, for the following request:

text

GET https://jsonplaceholder.typicode.com/posts?api-key=123

The plugin generates the following HTTP file:

HTTP

@jsonplaceholder_typicode_com_api_key = api-key

###

# @name getPosts

GET https://jsonplaceholder.typicode.com/posts?api-key=
{{jsonplaceholder_typicode_com_api_key}}
Host: jsonplaceholder.typicode.com
User-Agent: curl/8.6.0
Accept: */*
Via: 1.1 dev-proxy/0.27.0

The plugin creates variables for each combination of hostname and request header/query
string parameter. If multiple requests use the same combination, the plugin reuses the variable.
LatencyPlugin
Article • 04/30/2025

Delays responses by a random number of milliseconds from the configured range.

Plugin instance definition


JSON

{
"name": "LatencyPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "latencyPlugin"
}

Configuration example
JSON

{
"latencyPlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/latencyplugin.schema.json",
"minMs": 200,
"maxMs": 10000
}
}

Configuration properties
ノ Expand table

Property Description Default

minMs The minimum amount of delay added to a request in milliseconds. 0

maxMs The maximum amount of delay added to a request in milliseconds. Max value is 5000
10000 (10 s)

Command line options


None

Next step
Simulate slow API responses
MinimalCsomPermissionsPlugin
Article • 04/30/2025

Detects minimal permissions needed to call the recorded SharePoint Client-Side Object Model
(CSOM) API requests.

Plugin instance definition


JSON

{
"name": "MinimalCsomPermissionsPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "minimalCsomPermissionsPlugin"
}

Configuration example
JSON

{
"minimalCsomPermissionsPlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/minimalcsompermissionsplugin.schema.json",
"typesFilePath": "./api-specs"
}
}

Configuration properties
ノ Expand table

Property Description Default

typesFilePath Path to the file that lists permissions required to call ~appFolder/config/spo-csom-
SharePoint CSOM APIs types.json

Command line options


None

Remarks
The MinimalCsomPermissionsPlugin plugin detects what permissions the client application
needs at minimum to call the set of SharePoint CSOM APIs. To detect these minimal
permissions, the plugin uses information about permissions for SharePoint CSOM APIs located
in the specified SharePoint CSOM types file.

SharePoint CSOM types file


The MinimalCsomPermissionsPlugin uses a CSOM types file to determine what minimal
permissions the client application needs to call the specific set of CSOM APIs. The CSOM types
file is a JSON file that contains information about SharePoint CSOM types and their
permissions. The following example shows an example CSOM types file:

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/minimalcsompermissions.types.schema.json",
"types": {
"268004ae-ef6b-4e9b-8425-127220d84719":
"Microsoft.Online.SharePoint.TenantAdministration.Tenant",
"3747adcd-a3c3-41b9-bfab-4a64dd2f1e0a":
"Microsoft.SharePoint.Client.RequestContext"
},
"returnTypes": {
"Microsoft.SharePoint.Client.RequestContext.Current.Site":
"Microsoft.SharePoint.Client.Site"
},
"actions": {
"Microsoft.SharePoint.Client.RequestContext.Current": {
"delegated": [
"AllSites.Read",
"AllSites.Write",
"AllSites.Manage",
"AllSites.FullControl"
],
"application": []
},
"Microsoft.SharePoint.Client.Site.setProperty": {
"delegated": [
"AllSites.FullControl"
],
"application": []
},
"Microsoft.Online.SharePoint.TenantAdministration.Tenant.ctor": {
"delegated": [
"AllSites.Read",
"AllSites.Write",
"AllSites.Manage",
"AllSites.FullControl"
],
"application": [
]
},
"Microsoft.Online.SharePoint.TenantAdministration.Tenant.query": {
"delegated": [
"AllSites.Write",
"AllSites.Manage",
"AllSites.FullControl"
],
"application": [
]
},

"Microsoft.Online.SharePoint.TenantAdministration.Tenant.GetSitePropertiesFromShar
ePointByFilters": {
"delegated": [
"AllSites.FullControl"
],
"application": [
]
}
}
}

The file consists of three main parts:


types
returnTypes

actions

The types section contains a list of SharePoint CSOM types and their IDs. This section is
included for readability because it's easier to understand
Microsoft.SharePoint.Client.RequestContext.Current than 3747adcd-a3c3-41b9-bfab-
4a64dd2f1e0a.Current .

The returnTypes section contains a list of return types for the methods in the actions section.
The plugin uses this information when parsing CSOM requests to traverse the hierarchy of the
CSOM APIs.

The actions section contains a list of actions that can be performed using SharePoint CSOM
APIs. For each action, it lists the delegated and application permissions that a client application
can use to perform this action. Permissions are sorted ascending by their privilege, so that the
least privileged permissions are listed first.

As of today, the CSOM types file that we include with Dev Proxy, is incomplete. We're working
together with our community to document more types. Meanwhile, you can update it to
include the types and permissions that you need if the information that you need is missing.
You can then use your own types file. We encourage you to contribute your changes back to
the community so that we can all benefit from them, by creating a pull request in the Dev
Proxy samples repository . We regularly pull the latest changes from the repository to the Dev
Proxy repository so that you can benefit from the latest changes without having to update your
Dev Proxy installation.
MinimalPermissionsPlugin
Article • 04/30/2025

Detects the minimal permissions needed to perform the specified API operations. Uses API
information from the specified local folder.

Plugin instance definition


JSON

{
"name": "MinimalPermissionsPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "minimalPermissionsPlugin"
}

Configuration example
JSON

{
"minimalPermissionsPlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/minimalpermissionsplugin.schema.json",
"apiSpecsFolderPath": "./api-specs"
}
}

Configuration properties
ノ Expand table

Property Description Default

apiSpecsFolderPath Relative or absolute path to the folder with API specs None

Command line options


None

Remarks
The MinimalPermissionsPlugin plugin checks if the app uses minimal permissions to call APIs.
To check permissions, the plugin uses information about APIs located in the specified local
folder.

Define API permissions


The MinimalPermissionsPlugin plugin supports checking OAuth permissions for APIs secured
with OAuth. The plugin computes the minimal permissions required to call the APIs used in the
app using the information from the provided API specifications.

To define permissions for your APIs, include them in the OpenAPI definition of your API. The
following example shows how to define permissions for an API in an OpenAPI definition:

JSON

{
"openapi": "3.0.1",
"info": {
"title": "Northwind API",
"description": "Northwind API",
"version": "v1.0"
},
"servers": [
{
"url": "https://api.northwind.com"
}
],
"components": {
"securitySchemes": {
"OAuth2": {
"type": "oauth2",
"flows": {
"authorizationCode": {
"authorizationUrl":
"https://login.microsoftonline.com/common/oauth2/authorize",
"tokenUrl": "https://login.microsoftonline.com/common/oauth2/token",
"scopes": {
"customer.read": "Grants access to ready customer info",
"customer.readwrite": "Grants access to read and write customer
info"
}
}
}
}
},
"schemas": {
"Customer": {
"type": "object",
// [...] trimmed for brevity
}
}
},
"paths": {
"/customers/{customers-id}": {
"description": "Provides operations to manage a customer",
"get": {
"summary": "Get customer by ID",
"operationId": "getCustomerById",
"security": [
{
"OAuth2": [
"customer.read"
]
},
{
"OAuth2": [
"customer.readwrite"
]
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json; charset=utf-8": {
"schema": {
"$ref": "#/components/schemas/Customer"
}
}
}
}
}
},
"patch": {
"summary": "Update customer by ID",
"operationId": "updateCustomerById",
"security": [
{
"OAuth2": [
"customer.readwrite"
]
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Customer"
}
}
}
},
"responses": {
"204": {
"description": "No Content"
}
}
},
"parameters": [
{
"name": "customers-id",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
]
}
},
"x-ms-generated-by": {
"toolName": "Dev Proxy",
"toolVersion": "0.22.0"
}
}

The relevant part is the securitySchemes section, where you define the OAuth scopes that the
API uses. Then, for each operation, you include the required scopes in the security section.

Replace variables in API specs


Some API specs might contain variables in server URLs. Using variables is a common practice to
accommodate different environments (for example, development, staging, production), API
versions, or tenants. A URL with a variable looks like this:

yml

openapi: 3.0.4
info:
title: SharePoint REST API
description: SharePoint REST API
version: v1.0
servers:
- url: https://{tenant}.sharepoint.com
variables:
tenant:
default: contoso

The MinimalPermissionsPlugin plugin supports replacing variables in the API specs contents. To
replace a variable, start Dev Proxy with the --env option and specify the variable name and
value. For example, to replace the tenant variable with contoso , use the following command:

Bash

devproxy --env tenant=northwind

This command replaces the tenant variable in the API specs with the value northwind . The
plugin uses the replaced URL to check if the app uses minimal permissions to call APIs.

More information
OpenAPI Authentication and Authorization
OpenAPI specification Security Scheme Object
MinimalPermissionsGuidancePlugin
Article • 04/30/2025

Compares the permissions used in the JWT token sent to APIs against the minimum required
scopes needed for requests that proxy recorded and shows the difference.

Plugin instance definition


JSON

{
"name": "MinimalPermissionsGuidancePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "minimalPermissionsGuidancePlugin"
}

Configuration example
JSON

{
"minimalPermissionsGuidancePlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/minimalpermissionsguidanceplugin.schema.json",
"apiSpecsFolderPath": "./api-specs"
}
}

Configuration properties
ノ Expand table

Property Description Default

apiSpecsFolderPath Relative or absolute path to the folder with API specs None

Command line options


None

Remarks
The MinimalPermissionsGuidancePlugin plugin checks if the app uses minimal permissions to
call APIs. To check permissions, the plugin uses information about APIs located in the specified
local folder.

Define API permissions


The MinimalPermissionsGuidancePlugin plugin supports checking OAuth permissions for APIs
secured with OAuth. The plugin computes the minimal permissions required to call the APIs
used in the app using the information from the provided API specifications. Then, the plugin
compares the permissions used in the JSON Web Token (JWT) token against the minimum
required scopes needed for the requests that Dev Proxy recorded.

To define permissions for your APIs, include them in the OpenAPI definition of your API. The
following example shows how to define permissions for an API in an OpenAPI definition:

JSON

{
"openapi": "3.0.1",
"info": {
"title": "Northwind API",
"description": "Northwind API",
"version": "v1.0"
},
"servers": [
{
"url": "https://api.northwind.com"
}
],
"components": {
"securitySchemes": {
"OAuth2": {
"type": "oauth2",
"flows": {
"authorizationCode": {
"authorizationUrl":
"https://login.microsoftonline.com/common/oauth2/authorize",
"tokenUrl": "https://login.microsoftonline.com/common/oauth2/token",
"scopes": {
"customer.read": "Grants access to ready customer info",
"customer.readwrite": "Grants access to read and write customer
info"
}
}
}
}
},
"schemas": {
"Customer": {
"type": "object",
// [...] trimmed for brevity
}
}
},
"paths": {
"/customers/{customers-id}": {
"description": "Provides operations to manage a customer",
"get": {
"summary": "Get customer by ID",
"operationId": "getCustomerById",
"security": [
{
"OAuth2": [
"customer.read"
]
},
{
"OAuth2": [
"customer.readwrite"
]
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json; charset=utf-8": {
"schema": {
"$ref": "#/components/schemas/Customer"
}
}
}
}
}
},
"patch": {
"summary": "Update customer by ID",
"operationId": "updateCustomerById",
"security": [
{
"OAuth2": [
"customer.readwrite"
]
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Customer"
}
}
}
},
"responses": {
"204": {
"description": "No Content"
}
}
},
"parameters": [
{
"name": "customers-id",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
]
}
},
"x-ms-generated-by": {
"toolName": "Dev Proxy",
"toolVersion": "0.22.0"
}
}

The relevant part is the securitySchemes section, where you define the OAuth scopes that the
API uses. Then, for each operation, you include the required scopes in the security section.
Replace variables in API specs
Some API specs might contain variables in server URLs. Using variables is a common practice to
accommodate different environments (for example, development, staging, production), API
versions, or tenants. A URL with a variable looks like this:

yml

openapi: 3.0.4
info:
title: SharePoint REST API
description: SharePoint REST API
version: v1.0
servers:
- url: https://{tenant}.sharepoint.com
variables:
tenant:
default: contoso

The MinimalPermissionsGuidancePlugin plugin supports replacing variables in the API specs


contents. To replace a variable, start Dev Proxy with the --env option and specify the variable
name and value. For example, to replace the tenant variable with contoso , use the following
command:

Bash

devproxy --env tenant=northwind

This command replaces the tenant variable in the API specs with the value northwind . The
plugin uses the replaced URL to check if the app uses minimal permissions to call APIs.

More information
OpenAPI Authentication and Authorization
OpenAPI specification Security Scheme Object
MockGeneratorPlugin
Article • 04/08/2024

Generates Dev Proxy mocks based on the intercepted requests. Writes generated mocks
to a file named mocks-yyyyMMddHHmmss.json in the current working folder.

To intercept requests, after starting Dev Proxy, start recording. When you're done, stop
recording. Dev Proxy will generate mocks for the intercepted requests and write them to
a file named mocks-yyyyMMddHHmmss.json in the current working folder.

Plugin instance definition


JSON

{
"name": "MockGeneratorPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
}

Configuration example
None

Configuration properties
None

Command line options


None

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
MockRequestPlugin
Article • 04/30/2025

Allows you to issue web requests using Dev Proxy. This plugin is convenient for simulating
requests such as webhook notifications.

To issue the configured request, press w in the command prompt session where Dev Proxy is
running.

Plugin instance definition


JSON

{
"name": "MockRequestPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "contosoNotification"
}

Configuration example
JSON
{
"contosoNotification": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/mockrequestplugin.schema.json",
"mockFile": "mock-request.json"
}
}

Configuration properties
ノ Expand table

Property Description Default

mockFile Path to the file containing the mock request mock-request.json

Command line options


None

Mock request file example


JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/mockrequestplugin.mockfile.schema.json",
"request": {
"url": "http://localhost:3000/api/notification",
"method": "POST",
"body": {
"property1": "value1",
"property2": "value2"
}
}
}

Mock request file properties


ノ Expand table
Property Description Required

request Defines the request that Dev Proxy should issue. Yes

Mock request properties

ノ Expand table

Property Description Required Default

url URL that Dev Proxy should call. Yes empty

method HTTP method that Dev Proxy should use. No POST

body Body of the request that Dev Proxy should send. No empty

headers Array of request headers that Dev Proxy should send with the request. No empty

You can configure body to a string or a JSON object.

Mock request headers

ノ Expand table

Property Description Required

name Request header name. Yes

value Request header value. Yes


MockResponsePlugin
Article • 04/30/2025

Simulates responses.

Plugin instance definition


JSON

{
"name": "MockResponsePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "mocksPlugin"
}

Configuration example
JSON

{
"mocksPlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/mockresponseplugin.schema.json",
"mocksFile": "mocks.json"
}
}

Configuration properties
ノ Expand table

Property Description Default

mocksFile Path to the file containing mock responses mocks.json

blockUnmockedRequests Return 502 Bad Gateway response for requests that aren't mocked false

Command line options


ノ Expand table

Name Description Default

-n, --no-mocks Disable loading mock requests false

--mocks-file Path to the file containing mock responses -

Mocks file examples


Following are examples of mock objects.

Respond with body


Response to a request with a 200 OK response and a JSON body.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/mockresponseplugin.mocksfile.schema.json",
"mocks": [
{
"request": {
"url": "https://graph.microsoft.com/v1.0/me",
"method": "GET"
},
"response": {
"body": {
"@odata.context":
"https://graph.microsoft.com/v1.0/$metadata#users/$entity",
"businessPhones": ["+1 412 555 0109"],
"displayName": "Megan Bowen",
"givenName": "Megan",
"jobTitle": "Auditor",
"mail": "[email protected]",
"mobilePhone": null,
"officeLocation": "12/1110",
"preferredLanguage": "en-US",
"surname": "Bowen",
"userPrincipalName": "[email protected]",
"id": "48d31887-5fad-4d73-a9f5-3c356e68a038"
},
"headers": [
{
"name": "content-type",
"value": "application/json; odata.metadata=minimal"
}
]
}
}
]
}

Respond with error


Respond to a request with a 404 Not Found response.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/mockresponseplugin.mocksfile.schema.json",
"mocks": [
{
"request": {
"url": "https://graph.microsoft.com/v1.0/me/photo",
"method": "GET"
},
"response": {
"statusCode": 404
}
}
]
}

Respond with binary data


Respond to a request with a binary image loaded from a file on disk.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/mockresponseplugin.mocksfile.schema.json",
"mocks": [
{
"request": {
"url": "https://graph.microsoft.com/v1.0/users/*/photo/$value",
"method": "GET"
},
"response": {
"body": "@picture.jpg",
"headers": [
{
"name": "content-type",
"value": "image/jpeg"
}
]
}
}
]
}

Respond on nth request


Respond to a request only after the second time it's called.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/mockresponseplugin.mocksfile.schema.json",
"mocks": [
{
"request": {
"url":
"https://graph.microsoft.com/v1.0/external/connections/*/operations/*",
"method": "GET",
"nth": 2
},
"response": {
"statusCode": 200,
"body": {
"id":
"1.neu.0278337E599FC8DBF5607ED12CF463E4.6410CCF8F6DB8758539FB58EB56BF8DC",
"status": "completed",
"error": null
}
}
}
]
}

Respond matching the request body


Respond to a request that contains a specific string in the body.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/mockresponseplugin.mocksfile.schema.json",
"mocks": [
{
"request": {
"url": "https://login.microsoftonline.com/fa15d692-e9c7-4460-a743-
29f29522229/oauth2/v2.0/token",
"method": "POST",
"bodyFragment": "scope=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Fapi.contoso.com%2FDocuments.Read"
},
"response": {
"headers": [
{
"name": "Content-Type",
"value": "application/json; charset=utf-8"
}
],
"body": {
"token_type": "Bearer",
"expires_in": 3599,
"ext_expires_in": 3599,
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSU..."
}
}
}
]
}

Mocks file properties


ノ Expand table

Property Description Required

request Request object that defines the request to respond to yes


Property Description Required

response Response object that defines the response to return yes

Request object
Each request has the following properties:

ノ Expand table

Property Description Required Default Sample value


value

url Absolute URL to yes https://jsonplaceholder.typicode.com/posts


an API endpoint to
respond to

method HTTP verb used to no GET GET


match request
with url

nth Determines that no 2


proxy should
respond only after
when intercepting
the request for the
nth time

bodyFragment A string that no foo


should be present
in the request
body

Remarks
Use asterisk ( * ) in the url property if you want to match any series of characters in the URL.
For example, https://jsonplaceholder.typicode.com/* matches
https://jsonplaceholder.typicode.com/posts and

https://jsonplaceholder.typicode.com/comments . On runtime, Dev Proxy converts each * into

a regular expression .* .

When defining mocks, place the most specific mocks first. For example, if you have two mocks,
one for https://jsonplaceholder.typicode.com/posts and one for
https://jsonplaceholder.typicode.com/* , place the first mock first. Otherwise, Dev Proxy
matches the second mock first and return the response for
https://jsonplaceholder.typicode.com/* for all requests.

Use the nth property if you need to send a different to the same request URL. For example,
use it to simulate a long-running operation. The first time you call the API, it returns a response
with an inprogress message. The second time you call the API, it returns a response with the
completed message. For more information about the nth property, see Mock nth request.

Using the bodyFragment property, you can match requests based on the body content. For
example, if you want to match requests that contain the foo string in the body, set the
bodyFragment property to foo . Dev Proxy uses bodyFragment only for requests other than GET .

Response object
Each response has the following properties:

ノ Expand table

Property Description Required Default Sample value


value

body Body to send as the no empty { "foo": "bar" }


response to the request

statusCode Response HTTP status no 200 404


code

headers Array of headers to no empty [{ name: "content-type", "value":


include in the response "application/json" }]

Remarks

If you want to return binary data, set the body property to a string value that starts with @
followed by file path relative to the mocks file. For example, @picture.jpg returns the image
stored in the picture.jpg file in the same directory as the mocks file.

Next step
Mock responses
ODataPagingGuidancePlugin
Article • 04/08/2024

Shows a warning when proxy intercepts an OData paging request using a URL that
hasn't been previously returned in one of the intercepted responses.

Plugin instance definition


JSON

{
"name": "ODataPagingGuidancePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
}

Configuration example
None

Configuration properties
None

Command line options


None

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
OpenAIMockResponsePlugin
Article • 04/30/2025

Simulates responses from Azure OpenAI and OpenAI using a local language model.

Plugin instance definition


JSON

{
"name": "OpenAIMockResponsePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
}

Configuration example
None

Configuration properties
None
Command line options
None

Remarks
The OpenAIMockResponsePlugin plugin simulates responses from Azure OpenAI and OpenAI
using a local language model. Using this plugin allows you to emulate using a language model
in your app without connecting to the OpenAI or Azure OpenAI service and incurring costs.

The plugin uses the Dev Proxy language model configuration to communicate with a local
language model. To use this plugin, configure Dev Proxy to use a local language model.

) Important

The accuracy of the responses generated by the plugin depends on the local language
model that you use. Before deploying your app to production, be sure to test it with the
language model that you plan to use in production.

The OpenAIMockResponsePlugin plugin simulates completions and chat completions. The plugin
doesn't support other OpenAI API endpoints.

Next step
Simulate Azure OpenAI API
OpenApiSpecGeneratorPlugin
Article • 04/30/2025

Generates OpenAPI spec in JSON format from the intercepted requests and responses.

Plugin instance definition


JSON

{
"name": "OpenApiSpecGeneratorPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "openApiSpecGeneratorPlugin"
}

Configuration example
JSON

{
"openApiSpecGeneratorPlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/openapispecgeneratorplugin.schema.json",
"includeOptionsRequests": false,
"specVersion": "v3_0",
"specFormat": "Json"
}
}
Configuration properties
ノ Expand table

Property Description Default

includeOptionsRequests Determines whether to include OPTIONS requests in the generated false


OpenAPI spec

specVersion Determines which version to use for the generated OpenAPI spec. v3_0
Can be set to v2_0 or v3_0

specFormat Determines which format to use for the generated OpenAPI spec. Json
Can be set to Json or Yaml

Command line options


None

Remarks
To create better OpenAPI specs, consider using a local language model with Dev Proxy. Using a
local language model, the OpenApiSpecGeneratorPlugin generates clearer operation IDs and
descriptions, giving you a better starting point for your OpenAPI spec. To use a local language
model with the OpenApiSpecGeneratorPlugin , enable the language model in the configuration
file. For more information, see Use a local language model.

Next step
Generate an OpenAPI spec
RateLimitingPlugin
Article • 04/30/2025

Simulates rate-limit behaviors.

Plugin instance definition


JSON

{
"name": "RateLimitingPlugin",
"enabled": false,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "rateLimiting"
}

Configuration example
JSON

{
"rateLimiting": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/ratelimitingplugin.schema.json",
"costPerRequest": 2,
"rateLimit": 120
}
}

Configuration properties
ノ Expand table

Property Description Default

headerLimit Name of the response header that communicates the RateLimit-Limit


rate-limiting limit

headerRemaining Name of the response header that communicates the RateLimit-


remaining number of resources before the reset Remaining

headerReset Name of the response header that communicates the RateLimit-Reset


time remaining until the reset

headerRetryAfter Name of the response header that communicates the Retry-After


retry-after period

costPerRequest How many resources does a request cost 2

resetTimeWindowSeconds How long in seconds until the next reset 60

warningThresholdPercent The percentage of use that's when exceeded starts 80


returning rate limiting response headers

rateLimit Number of resources for a time window 120

whenLimitExceeded The behavior the plugin should use when limit is Throttle
exceeded. Use Throttle or Custom .

resetFormat The format used to determine when the rate limit SecondsLeft
resets. Use SecondsLeft or UtcEpochSeconds .

customResponseFile File containing a custom error response used when limit rate-limit-
is exceeded. response.json

Command line options


None

Next step
Simulate Rate-Limit API responses
RetryAfterPlugin
Article • 04/30/2025

Simulates the Retry-After header sent by an API after throttling a request. This plugin also
shows a warning when proxy detects a subsequent request to the same URL before the Retry-
After time elapses.

Plugin instance definition


JSON

{
"name": "RetryAfterPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
}

Configuration example
None
Configuration properties
None

Command line options


None

Next step
Simulate throttling on Microsoft 365 APIs
RewritePlugin
Article • 04/30/2025

Rewrites requests.

Plugin instance definition


JSON

{
"name": "RewritePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "rewritePlugin"
}

Configuration example
JSON

{
"rewritePlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/rewriteplugin.schema.json",
"rewritesFile": "rewrites.json"
}
}

Configuration properties
ノ Expand table

Property Description Default

rewritesFile Path to the file containing rewrite definitions rewrites.json

Command line options


None

Rewrite file examples


Following are examples of rewrite rules.

Rewrite all requests from HTTP to HTTPS


Rewrite all requests from HTTP to HTTPS. In this context, all means all requests configured with
Dev Proxy or the RewritePlugin.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/rewriteplugin.rewritesfile.schema.json",
"rewrites": [
{
"in": {
"url": "^http://(.*)"
},
"out": {
"url": "https://$1"
}
}
]
}

Mocks file properties


ノ Expand table

Property Description Required

rewrites Array of rewrite objects that defines the list of rewrite rules that the RewritePlugin yes
applies to the requests it intercepts

Rewrite object
Each rewrite rule has the following properties:

ノ Expand table

Property Description Required

in Rewrite pattern to match the incoming request. yes

out Rewrite pattern to rewrite the request yes

Remarks

If the request that the RewritePlugin intercepts, doesn't match all properties defined in the in
pattern, the plugin doesn't apply the rewrite rule to the request.

Rewrite pattern
Each rewrite pattern has the following properties:

ノ Expand table

Property Description Required Default Sample


value value

url Regular expression that the plugin applies to the yes ^http://(.*)
URL.

Remarks
If you use capture groups in the regular expression in the in patterns, you can refer to them in
the out pattern. For example, if you want to rewrite http://example.com/foo to
https://example.com/foo , you can use the following rewrite rule:

JSON
{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/rewriteplugin.rewritesfile.schema.json",
"rewrites": [
{
"in": {
"url": "^http://(.*)"
},
"out": {
"url": "https://$1"
}
}
]
}
TypeSpecGeneratorPlugin
Article • 04/15/2025

Generates TypeSpec files from the intercepted requests and responses.

Plugin instance definition


JSON

{
"name": "TypeSpecGeneratorPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "typeSpecGeneratorPlugin"
}

Configuration example
JSON

{
"typeSpecGeneratorPlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/typespecgeneratorplugin.schema.json",
"ignoreResponseTypes": false
}
}

Configuration properties
ノ Expand table

Property Description Default

ignoreResponseTypes Determines whether to generate types for API responses ( false ) or to false
set them to string ( true ).

Command line options


None

Remarks
To create better TypeSpec files, consider using a local language model with Dev Proxy. Using a
local language model, the TypeSpecGeneratorPlugin generates clearer operation IDs and
descriptions, giving you a better starting point for your TypeSpec file. To use a local language
model with the TypeSpecGeneratorPlugin , enable the language model in the configuration file.
For more information, see Use a local language model.
UrlDiscoveryPlugin
Article • 04/30/2025

Creates a list of URLs that Dev Proxy intercepted. Use this plugin to learn which URLs your app
is calling and how to configure the Dev Proxy to simulate behaviors for them.

 Tip

To save the summary to a file, use a reporter plugin in your configuration.

Plugin instance definition


JSON

{
"name": "UrlDiscoveryPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
}

Configuration example
None
Configuration properties
None

Next step
Discover URLs to watch
GraphBetaSupportGuidancePlugin
Article • 04/08/2024

Shows a warning when proxy detects a request to Microsoft Graph beta endpoint.

Plugin instance definition


JSON

{
"name": "GraphBetaSupportGuidancePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"urlsToWatch": [
"https://graph.microsoft.com/beta/*",
"https://graph.microsoft.us/beta/*",
"https://dod-graph.microsoft.us/beta/*",
"https://microsoftgraph.chinacloudapi.cn/beta/*"
]
}

Configuration example
None

Configuration properties
None

Command line options


None

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
GraphClientRequestIdGuidancePlugin
Article • 04/08/2024

Shows a tip when a request to Microsoft Graph API doesn't include the client-request-
id header.

Plugin instance definition


JSON

{
"name": "GraphClientRequestIdGuidancePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"urlsToWatch": [
"https://graph.microsoft.com/v1.0/*",
"https://graph.microsoft.com/beta/*",
"https://graph.microsoft.us/v1.0/*",
"https://graph.microsoft.us/beta/*",
"https://dod-graph.microsoft.us/v1.0/*",
"https://dod-graph.microsoft.us/beta/*",
"https://microsoftgraph.chinacloudapi.cn/v1.0/*",
"https://microsoftgraph.chinacloudapi.cn/beta/*"
]
}

Configuration example
None

Configuration properties
None

Command line options


None

6 Collaborate with us on
GitHub Dev Proxy feedback
The source for this content can Dev Proxy is an open source project.
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
GraphConnectorGuidancePlugin
Article • 03/13/2024

Shows contextual guidance for working with Microsoft Graph connectors.

This plugin detects the following issues:

ノ Expand table

Issue Request Level

Schema missing PATCH Failure


one or more https://graph.microsoft.com/v1.0/external/connections/{id}/schema
semantic labels
required for
Microsoft
Copilot for
Microsoft 365

Plugin instance definition


JSON

{
"name": "GraphConnectorGuidancePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"urlsToWatch": [
"https://graph.microsoft.com/*/external/connections/*/schema",
"https://graph.microsoft.us/*/external/connections/*/schema",
"https://dod-graph.microsoft.us/*/external/connections/*/schema",

"https://microsoftgraph.chinacloudapi.cn/*/external/connections/*/schema"
]
}

Configuration example
None

Configuration properties
None

Command line options


None

6 Collaborate with us on
GitHub Dev Proxy feedback
The source for this content can Dev Proxy is an open source project.
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
GraphConnectorNotificationPlugin
Article • 02/05/2025

Simulates the notification when enabling or disabling a Microsoft Graph connector in


Teams Admin Center (TAC). Validates requests for creating and deleting the external
connection.

To issue the configured notification request, press w in the command prompt session
where Dev Proxy is running.

Issuing notification requests


The GraphConnectorNotificationPlugin extends the MockRequestPlugins with extra
functionality to simulate notifications from TAC.

ノ Expand table

Token Description

@dynamic.validationToken JWT token to validate the authenticity of the notification. Dev Proxy
replaces it with a valid JWT token, signed by the Dev Proxy CA
certificate.
Validating handling notifications and issuing
Graph connector requests
Next to simulating the notification requests, the GraphConnectorNotificationPlugin
validates if the notification API, properly handles notifications and issues correct
Microsoft Graph requests.

For handling TAC notifications, the plugin checks if the API sends a 202 Accepted
response without a body. Additionally, the plugin inspects POST and DELETE requests to
the /external/connections/* Microsoft Graph endpoint. It checks if the request contains
the GraphConnectors-Ticket header with the ticket specified in the notification. If either
of the checks fails, the plugin logs an error.

Plugin instance definition


JSON

{
"name": "GraphConnectorNotificationPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "graphConnectorNotificationEnabled"
}

Configuration example
JSON

{
"graphConnectorNotificationEnabled": {
"mockFile": "graph-connector-notification-enabled.json",
"tenant": "fa15d692-e9c7-4460-a743-29f29522229",
"audience": "00001111-aaaa-2222-bbbb-3333cccc4444"
}
}

Configuration properties
ノ Expand table
Property Description Default Required

audience The Microsoft Entra app registration ID that the empty Yes
Microsoft Graph connector uses to authenticate the
notification request

mockFile Path to the file containing the mock request mock- Yes
request.json

tenant The tenant ID where the Microsoft Graph connector empty Yes
creates the external connection

Command line options


None

Mock request file example


Following are several examples of API files that define a CRUD API for information about
customers.

Enable a Microsoft Graph connector TAC notification


Following is an example of a notification that Teams Admin Center sends, when a user
enables a Microsoft Graph connector.

JSON

{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.24.0/mockrequestplugin.schema.json",
"request": {
"url": "http://localhost:3000/api/notification",
"method": "POST",
"body": {
"value": [
{
"changeType": "updated",
"subscriptionId": "aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e",
"resource": "external",
"clientState": null,
"resourceData": {
"@odata.type": "#Microsoft.Graph.connector",
"@odata.id": "external",
"id": "35177924-33fc-444d-bd51-f059ce385ec2",
"state": "enabled",
"connectorsTicket":"eyJhbGciOiJIUzI1"
},
"subscriptionExpirationDateTime": "2021-06-26T12:40:26.4436785-
07:00",
"tenantId": "fa15d692-e9c7-4460-a743-29f29522229"
}
],
"validationTokens": [ "@dynamic.validationToken" ]
}
}
}
GraphMinimalPermissionsPlugin
Article • 04/30/2025

Returns a list of the minimal permissions required for Microsoft Graph requests that proxy
recorded.

Plugin instance definition


JSON

{
"name": "GraphMinimalPermissionsPlugin",
"enabled": false,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "graphMinimalPermissionsPlugin"
}

Configuration example
JSON
{
"graphMinimalPermissionsPlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/graphminimalpermissionsplugin.schema.json",
"type": "delegated"
}
}

Configuration properties
ノ Expand table

Property Description Default

type Determines which type of permission scopes to return. Can be Delegated or Delegated
Application

Command line options


None

Next step
Detect minimal Microsoft Graph API permissions
GraphMinimalPermissionsGuidancePlugin
Article • 04/30/2025

Compares the permissions used in the JWT token sent to Microsoft Graph against the
minimum required scopes needed for requests that proxy recorded and shows the difference.

Plugin instance definition


JSON

{
"name": "GraphMinimalPermissionsGuidancePlugin",
"enabled": false,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "graphMinimalPermissionsGuidancePlugin"
}

Configuration example
JSON
{
"graphMinimalPermissionsGuidancePlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/graphminimalpermissionsguidanceplugin.schema.json",
"permissionsToIgnore": [
"profile",
"openid",
"offline_access",
"email"
]
}
}

Configuration properties
ノ Expand table

Property Description Default

permissionsToIgnore The scopes to ignore and not include in the profile openid offline_access
report. email

Command line options


None

Next step
Check if you're using excessive Microsoft Graph API permissions
GraphMockResponsePlugin
Article • 04/08/2024

Mocks responses to Microsoft Graph APIs. Includes all functionality of the


MockResponsePlugin and adds support for mocking Microsoft Graph API batch
requests.

Plugin instance definition


JSON

{
"name": "GraphMockResponsePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "mocksPlugin"
}

Configuration example
See MockResponsePlugin

Configuration properties
See MockResponsePlugin
Command line options
See MockResponsePlugin

6 Collaborate with us on
GitHub Dev Proxy feedback
The source for this content can Dev Proxy is an open source project.
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
GraphRandomErrorPlugin
Article • 04/30/2025

Fails requests made to Microsoft Graph with random errors.

Plugin instance definition


JSON

{
"name": "GraphRandomErrorPlugin",
"enabled": false,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "graphRandomErrorPlugin"
}

Configuration example
JSON

{
"graphRandomErrorPlugin": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/graphrandomerrorplugin.schema.json",
"allowedErrors": [ 429, 500, 502, 503, 504, 507 ]
}
}

Configuration properties
ノ Expand table

Property Description Default

allowedErrors List of HTTP status codes that Dev Proxy might produce. 429 500 502 503
504 507

rate The percentage of requests to fail with a random error. 50


Value between 0 and 100.

retryAfterInSeconds Value of the Retry-After header in seconds. 5

Command line options


ノ Expand table

Name Description Default

-a, --allowed-errors List of HTTP status codes that Dev Proxy might 429 500 502 503
produce. 504 507

-f, --failure-rate The percentage of requests to fail with a random error. 50


<failure rate> Value between 0 and 100.

HTTP error status codes used by Microsoft Graph


Microsoft Graph uses the following HTTP status codes.

 Tip

Descriptions from HTTP response status codes

ノ Expand table
Code Name Description

429 Too Many Indicates the user has sent too many requests in a given amount of time ("rate
Requests limiting"). A Retry-After header might be included to this response indicating
how long to wait before making a new request.

500 Internal Indicates that the server encountered an unexpected condition that prevented it
Server Error from fulfilling the request. This error response is a generic "catch-all" response.
Usually, this indicates the server can't find a better 5xx error code to response.

502 Bad Gateway Indicates that the server, while acting as a gateway or proxy, received an invalid
response from the upstream server.

503 Service Indicates that the server isn't ready to handle the request. Common causes are a
Unavailable server that is down for maintenance or that is overloaded. This response should
be used for temporary conditions and the Retry-After HTTP header should, if
possible, contain the estimated time for the recovery of the service.

504 Gateway Indicates that the server, while acting as a gateway or proxy, didn't get a response
Timeout in time from the upstream server that it needed in order to complete the request.

507 Insufficient Might be given in the context of the Web Distributed Authoring and Versioning
Storage (WebDAV) protocol (see RFC 4918 ). It indicates that a method couldn't be
performed because the server can't store the representation needed to
successfully complete the request.

Next step
Simulate errors from Microsoft Graph APIs
GraphSdkGuidancePlugin
Article • 04/30/2025

Shows a tip when proxy intercepts a request to Microsoft Graph that hasn't been issued by a
Microsoft Graph SDK.

Plugin instance definition


JSON

{
"name": "GraphSdkGuidancePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"urlsToWatch": [
"https://graph.microsoft.com/v1.0/*",
"https://graph.microsoft.com/beta/*",
"https://graph.microsoft.us/v1.0/*",
"https://graph.microsoft.us/beta/*",
"https://dod-graph.microsoft.us/v1.0/*",
"https://dod-graph.microsoft.us/beta/*",
"https://microsoftgraph.chinacloudapi.cn/v1.0/*",
"https://microsoftgraph.chinacloudapi.cn/beta/*"
]
}

Configuration example
None

Configuration properties
None

Command line options


None

Next step
Update my application code to use Microsoft Graph JavaScript SDK
GraphSelectGuidancePlugin
Article • 04/08/2024

Shows a warning when proxy intercepts a request to Microsoft Graph APIs that doesn't
include the $select query string parameter.

Plugin instance definition


JSON

{
"name": "GraphSelectGuidancePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"urlsToWatch": [
"https://graph.microsoft.com/v1.0/*",
"https://graph.microsoft.com/beta/*",
"https://graph.microsoft.us/v1.0/*",
"https://graph.microsoft.us/beta/*",
"https://dod-graph.microsoft.us/v1.0/*",
"https://dod-graph.microsoft.us/beta/*",
"https://microsoftgraph.chinacloudapi.cn/v1.0/*",
"https://microsoftgraph.chinacloudapi.cn/beta/*"
]
}

Configuration example
None

Configuration properties
None

6 Collaborate with us on
GitHub Dev Proxy feedback
The source for this content can Dev Proxy is an open source project.
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
ODSPSearchGuidancePlugin
Article • 01/16/2024

Shows a warning when Dev Proxy detects a request to OneDrive and SharePoint search
APIs.

This plugin follows the Microsoft Search APIs guidance .

This plugin detects the following requests:

graph.microsoft.com/{version}/drives/{drive-id}/root/search(q='{search-
text}')

graph.microsoft.com/{version}/groups/{group-id}/drive/root/search(q='{search-
text}')

graph.microsoft.com/{version}/me/drive/root/search(q='{search-text}')

graph.microsoft.com/{version}/sites/{site-id}/drive/root/search(q='{search-
text}')

graph.microsoft.com/{version}/users/{user-id}/drive/root/search(q='{search-
text}')

graph.microsoft.com/{version}/sites?search={query}

Plugin instance definition


JSON

{
"name": "ODSPSearchGuidancePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"urlsToWatch": [
"https://graph.microsoft.com/v1.0/*",
"https://graph.microsoft.com/beta/*",
"https://graph.microsoft.us/v1.0/*",
"https://graph.microsoft.us/beta/*",
"https://dod-graph.microsoft.us/v1.0/*",
"https://dod-graph.microsoft.us/beta/*",
"https://microsoftgraph.chinacloudapi.cn/v1.0/*",
"https://microsoftgraph.chinacloudapi.cn/beta/*"
]
}

Configuration example
None

Configuration properties
None

Command line options


None

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
JsonReporter
Article • 05/27/2024

Generates reports in JSON format.

Plugin instance definition


JSON

{
"name": "JsonReporter",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
}

Configuration example
None

Configuration properties
None

Remarks
JsonReporter stores reports in files named PluginName_JsonReporter.json .

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
MarkdownReporter
Article • 05/27/2024

Generates reports in Markdown format.

Plugin instance definition


JSON

{
"name": "MarkdownReporter",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
}

Configuration example
None

Configuration properties
None

Remarks
MarkdownReporter stores reports in files named PluginName_MarkdownReporter.md .

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
PlainTextReporter
Article • 05/27/2024

Generates reports in plain-text format.

Plugin instance definition


JSON

{
"name": "PlainTextReporter",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
}

Configuration example
None

Configuration properties
None

Remarks
PlainTextReporter stores reports in files named PluginName_PlainTextReporter.txt .

6 Collaborate with us on
GitHub Dev Proxy feedback
Dev Proxy is an open source project.
The source for this content can
Select a link to provide feedback:
be found on GitHub, where you
can also create and review
 Open a documentation issue
issues and pull requests. For
more information, see our
 Provide product feedback
contributor guide.
(root)
Article • 04/28/2025

Starts Dev Proxy.

Usage
Console

devproxy

Arguments
None

Options
ノ Expand table

Name Description Allowed values Default

--as-system- Whether to register Dev true , false true


proxy Proxy as the system proxy
on startup. When set to
true requires installCert
to be, set to true

-c, --config- The path to the Local file path devproxyrc.json


file configuration file
<configFile>

--discover Run Dev Proxy in discovery n/a n/a


mode

-e, --env <env> Variables to set for the Dev string key1=value n/a
Proxy process

--install-cert Whether to install the root true , false true


certificate

--ip-address The IP address for the IPv4 address 127.0.0.1


<ipAddress> proxy to bind to
Name Description Allowed values Default

--log-level Level of messages to log trace , debug , information , information


<loglevel> warning , error

--no-first-run Skip the first run n/a n/a


experience (don't trust
certificate on macOS)

-p, --port The port for the proxy integer 8000


<port> server to listen on

--record Use this option to record n/a n/a


all request logs

-t, --timeout Automatically stop proxy integer n/a


<seconds> after a period of inactivity

-u, --urls-to- List of URLs that proxy Absolute URL (can contain See devproxyrc
watch should intercept wildcards) for example, file
<urlsToWatch> "https://api.contoso.com/*"

--version Show version information n/a n/a

--watch-pids The IDs of processes to integer n/a


<pids> watch for requests

--watch-process- The names of processes to string n/a


names watch for requests
<processNames>

-?, -h, --help Show help and usage n/a n/a


information
cert ensure
Article • 03/31/2025

Ensures that the certificate that Dev Proxy uses for decrypting SSL traffic is set up.
Creates the certificate if it doesn't exist. Also, makes the certificate trusted.

Usage
Console

devproxy cert ensure

Arguments
None

Options
ノ Expand table

Name Description Allowed values Default

--log-level Level of messages to trace , debug , information , information


<loglevel> log warning , error
config get
Article • 03/31/2025

Download the specified config from the Sample Solution Gallery .

Usage
Console

devproxy config get <config-id>

Arguments
ノ Expand table

Name Description Required Default

<config-id> The ID of the config to download. Yes None

 Tip
Each sample lists its ID in the details section on the sample page in the Sample
Solution Gallery.

Options
ノ Expand table

Name Description Allowed values Default

--log-level Level of messages to trace , debug , information , information


<loglevel> log warning , error
config new
Article • 03/31/2025

Create new Dev Proxy configuration file. If a file exists with the same name, the created
file will have a number appended to it, for example, devproxyrc-2.json, and will
increment with each new file created with the same name.

Usage
Console

devproxy config new <name>

Arguments
ノ Expand table

Name Description Required Default

<name> Name of the configuration file. No devproxyrc.json


Options
ノ Expand table

Name Description Allowed values Default

--log-level Level of messages to trace , debug , information , information


<loglevel> log warning , error
config open
Article • 03/31/2025

Opens Dev Proxy config file (devproxyrc.json) in the default editor associated with JSON
files. If there's a devproxyrc.json file in the current directory, the command opens it in
the editor. Otherwise, the command opens the global Dev Proxy config file located in
the installation directory.

Usage
Console

devproxy config open

Arguments
None

Options
ノ Expand table

Name Description Allowed values Default

--log-level Level of messages to trace , debug , information , information


<loglevel> log warning , error
jwt create
Article • 03/31/2025

Creates a new JSON Web Token (JWT) for testing purposes.

Usage
Console

devproxy jwt create [options]

Example
Generates a JWT for a user named Megan Bowen with the issuer my-app and audience
https://myserver.com . The token includes the role admin , scopes read and write , and a

custom claim custom:claim . The token is valid for 120 minutes.

Console

devproxy jwt create --name "Megan Bowen" --issuer "my-app" --audience


"https://myserver.com" --roles "admin" --scopes "read" --scopes "write" --
claims "custom:claim" --valid-for 120

Arguments
None

Options
ノ Expand table

Name Description Allowed values Default

-n, --name The name of the user to create string Dev Proxy
the token for.

-i, --issuer The issuer of the token. string dev-proxy

-a, -- The audiences to create the string https://myserver.com


audience token for. Specify once for each
Name Description Allowed values Default

audience.

-r, --roles A role claim to add to the string None


token. Specify once for each
role.

-s, --scopes A scope claim to add to the string None


token. Specify once for each
scope.

--claims Claims to add to the token. None


Specify once for each claim in
the format name:value .

-v, --valid- The duration which the token is 60


for valid for. Duration is set in
minutes.

--signing-key The key to use to sign the Randomly generated


token. Must be at least 32
characters long.

--log-level Level of messages to log trace , debug , information


<loglevel> information ,
warning , error

7 Note

Registered claims (e.g. iss , sub , aud , exp , nbf , iat , jti ) are automatically added
to the token. If you specify any of these claims in the --claims option, the values
you provide will be ignored.
msgraphdb
Article • 03/31/2025

Updates the internal database of Microsoft Graph API metadata.

Usage
Console

devproxy msgraphdb

Arguments
None

Options
ノ Expand table
Name Description Allowed values Default

--log-level Level of messages to trace , debug , information , information


<loglevel> log warning , error
outdated
Article • 03/31/2025

Checks if the installed version is outdated and returns the version to upgrade to. The
newVersionNotification property devproxyrc.json file determines the version check

behavior.

Usage
Console

devproxy outdated

Arguments
None

Options
ノ Expand table

Name Description Allowed values Default

--log-level Level of messages to trace , debug , information , information


<loglevel> log warning , error

--short Return version only N/A N/A

You might also like