microsoft-cloud-dev-dev-proxy
microsoft-cloud-dev-dev-proxy
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.
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.
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.
Automated
Console
) 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
Console
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.
text
In PowerShell, use the Invoke-WebRequest cmdlet to send a GET request to the JSON
Placeholder API.
PowerShell
If you use curl , send a GET request to the JSON Placeholder API using the following
command.
Console
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
If Dev Proxy returns an error response, you see the error message in the output.
text
) 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.
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.
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
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
}
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.
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:
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
Node.js applications
Node.js applications in Docker
JavaScript Azure Functions
SharePoint Framework (SPFx) solutions
https://api.contoso.com/* .
Console
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.
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.
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
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.
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.
Node.js LTS .
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.
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.
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.
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 .
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.
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
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
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
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
To intercept request from processes by their given process names, use the --watch-
process-names option:
Console
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.
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.
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
) 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
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/*"
]
}
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.
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"
}
JSON
"devTools": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-
proxy/main/schemas/v0.27.0/devtoolsplugin.schema.json",
"preferredBrowser": "Edge"
}
Tip
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"
}
}
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.
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.
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 .
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.
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.
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.
Tip
If you use Visual Studio Code, consider installing the Dev Proxy Toolkit extension. It
significantly simplifies working with Dev Proxy configuration files.
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"
}
}
}
]
}
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"
}
]
}
}
]
}
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.
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:
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:
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"
}
]
}
}
]
}
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:
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"
}
}
}
]
}
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"
}
}
}
]
}
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
Console
Alternatively, you can specify the mocks file in the devproxyrc.json configuration file.
JSON
{
"mocksPlugin": {
"mocksFile": "mocks.json"
}
}
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"
}
}
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:
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:
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 .
) Important
At this moment, you can only expose HTTP CRUD APIs across the internet using
Dev Tunnels.
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"
}
]
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})]"
}
]
}
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
Console
[
{
"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"
}
]
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
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.
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.
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:
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
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.
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*"
]
}
JSON
{
// [...] trimmed for brevity
"languageModel": {
"enabled": true
}
}
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
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:
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.
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.
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
JSON
{
// [...] trimmed for brevity
"urlsToWatch": [
"https://api.openai.com/v1/chat/completions"
]
}
JSON
{
// [...] trimmed for brevity
"languageModel": {
"enabled": true
}
}
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
}
}
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
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:
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.
Console
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
}
}
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
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.
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
}
Follow the same steps as described previously when testing the notification for enabling
the Microsoft Graph connector.
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.
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
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"
}
}
]
}
]
}
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.
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
}
}
}
]
}
]
}
Console
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.
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.
ノ Expand table
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
JSON
{
"graphRandomErrorPlugin": {
"allowedErrors": [ 429 ]
}
}
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.
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.
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"
}
}
]
}
]
}
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
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.
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
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
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.
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.
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
Tip
Download the preset for this how to article by running in the command prompt
devproxy preset get demo-apicenter-minimalpermissions .
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 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.
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"
}
}
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...
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
◉ Recording...
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...
◉ Recording...
When Dev Proxy finishes its analysis, it creates a report in a file named
ApiCenterMinimalPermissionsPlugin_PlainTextReporter.txt with the following contents:
text
APIS
Northwind
Permissions
Requests
- GET https://api.northwind.com/customers/ALFKI
UNMATCHED REQUESTS
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:
The proxy returns a list of minimal permissions in the activity summary based on the
intercepted requests.
For example:
Console
Minimal permissions:
User.Read, Calendars.Read
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.
Dev Proxy returns a list of permissions scopes that are unnecessary in the activity
summary based on the intercepted requests.
For example:
text
- GET /me
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.
Record immediately. Start proxy with --record option, for example, devproxy --
record .
By default, activities grouped by URL. To group activity by message type, use the --
summary-group-by option.
Console
7 Note
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.
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 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.
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"
}
}
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
text
◉ Recording...
text
◉ Recording...
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.
The ApiCenterOnboardingPlugin uses this information to check if the APIs, that your app
is using, are registered in your organization.
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 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.
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
}
}
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
text
◉ Recording...
text
◉ Recording...
text
https://jsonplaceholder.typicode.com:
DELETE https://jsonplaceholder.typicode.com/posts/1
GET https://jsonplaceholder.typicode.com/posts
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.
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
◉ Recording...
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
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.
devproxy
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.
JSON
{
"plugins": [
{
"name": "TypeSpecGeneratorPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
}
]
// [...] shortened for brevity
}
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.
Console
devproxy
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.
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
JavaScript
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
function getGraphClient(account) {
const authProvider = new
MSGraphAuthCodeMSALBrowserAuthProvider.AuthCodeMSALBrowserAuthenticationProv
ider(msalClient, {
account,
scopes: [
'https://graph.microsoft.com/User.Read'
],
interactionType: msal.InteractionType.Popup,
});
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
});
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));
}
return response;
}
An easier way to handle throttling, and other errors, is to use the Graph JavaScript SDK,
which handles errors for you.
JavaScript
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
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
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.
JSON
{
"languageModel": {
"enabled": true
}
}
You can use the following options as part of the languageModel setting:
ノ Expand table
client The type of the client to use. Allowed values: Ollama , OpenAI
OpenAI
) Important
When using a local language model, be sure to start your local language model client
before starting Dev Proxy.
OpenAIMockResponsePlugin
OpenApiSpecGeneratorPlugin
TypeSpecGeneratorPlugin
Refresh local Microsoft Graph database
Article • 01/24/2024
Execute devproxy msgraphdb in your proxy installation folder to rebuild and update
your local database.
text
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.
Bash
7 Note
To try the latest preview features, use the beta version of the Dev Proxy container.
Bash
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 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.
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.
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
(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();
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
(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.
JavaScript
(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
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
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
(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
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
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
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.
C#
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.
Console
) 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.
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"
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
In your application, add the following code to ignore SSL certificate validation:
C#
ServicePointManager.ServerCertificateValidationCallback = (sender,
certificate, chain, sslPolicyErrors) => true;
U Caution
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.
Console
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
Console
Tip
You can specify multiple URLs to watch, for example --urls-to-watch
"http://localhost:5222/*" "http://localhost:5223/*"
Console
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
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.
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.
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
Here's an example of a bash script with job control enabled that starts Dev Proxy:
Bash
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
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
Bash
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
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
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
log_file=devproxy.log
proxy_pid=$!
# 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:""
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
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
YAML
- task: PublishPipelineArtifact@1
displayName: Upload Dev Proxy logs
inputs:
targetPath: $(LOG_FILE)
artifact: $(LOG_FILE)
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'
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
################################
# 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
- 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.
YAML
YAML
YAML
YAML
YAML
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"
#################################
# 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
################################
# 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 }}
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.
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.
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 .
Console
When you're done, you can reset the WinHTTP settings by using:
Console
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.
PowerShell
Console
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
text
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
text
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:
1. Create a new class library project using the dotnet new classlib command.
Console
Console
code MyCustomPlugin
XML
<ItemGroup>
<Reference Include="dev-proxy-abstractions">
<HintPath>.\dev-proxy-abstractions.dll</HintPath>
<Private>false</Private>
<ExcludeAssets>runtime</ExcludeAssets>
</Reference>
</ItemGroup>
Console
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>
C#
using Microsoft.DevProxy.Abstractions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace MyCustomPlugin;
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;
}
return Task.CompletedTask;
}
}
Console
dotnet build
JSON
{
"plugins": [{
"name": "CatchApiCalls",
"enabled": true,
"pluginPath": "./bin/Debug/net8.0/MyCustomPlugin.dll",
}]
}
devproxy
The example plugin checks all matching URLs for the required Authorization header. If
the header isn't present, it shows a warning message.
C#
using Microsoft.DevProxy.Abstractions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace MyCustomPlugin;
return Task.CompletedTask;
}
}
Console
dotnet build
JSON
{
"plugins": [{
"name": "CatchApiCalls",
"enabled": true,
"pluginPath": "./bin/Debug/net8.0/MyCustomPlugin.dll",
"configSection": "catchApiCalls"
}],
"catchApiCalls": {
"requiredHeader": "Authorization" // Example configuration
}
}
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.
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.
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:
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.
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.
Tools like Dev Proxy or custom proxy implementations are commonly used for this purpose in
integration and end-to-end tests.
When your application runs behind a reverse proxy, make sure that your framework or
platform is configured to trust and interpret these headers correctly.
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.
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 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.
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
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.
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
text
{
"statusCode": 429,
"message": "Rate limit is exceeded. Try again in 60 seconds."
}
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
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:
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:
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.
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
Here's why you should consider having an OpenAPI spec for your API:
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.
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.
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.
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.
Discover our how-to guides and unlock the full potential of Dev Proxy. Let's build the
future of APIs together!
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.
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!
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.
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.
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
CachingGuidancePlugin Shows a warning when Dev Proxy intercepted the same request
within the specified period of time.
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.
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.
OpenAIMockResponsePlugin Simulates responses from Azure OpenAI and OpenAI using a local
language model.
ノ 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.
Name Description
ノ Expand table
Name Description
ノ Expand table
Name Description
Configuration
Reference of Dev Proxy configuration options.
ノ Expand table
Name Description
Dev Proxy uses the following text labels in the console output.
ノ Expand table
Label Description
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
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
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:
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
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.
ノ Expand table
the proxy to
bind to
Proxy skips
running a
plugin.
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
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.
HTTP
GET http://localhost:8897/proxy
Response:
text
200 OK
{
"recording": false,
"configFile": "/Users/user/dev-proxy/devproxyrc.json"
}
POST /proxy
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"
}
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
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
Request:
HTTP
POST http://localhost:8897/proxy/stopproxy
Response:
text
202 Accepted
Models
ProxyInfo
ノ Expand table
configFile string Path to the configuration file that Dev Proxy is using (read-only)
JwtOptions
Options for generating a JWT token.
ノ Expand table
name string The name of the user to create the token for
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
The following table describes the keyboard shortcuts available when the proxy is
running.
ノ Expand table
Keyboard Description
r Start recording
s Stop recording
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.
{
"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
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.
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.
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"
}
}
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.
{
"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
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.
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
}
}
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.
{
"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
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.
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"
}
}
Next step
How to check if my app is using production-level APIs
AuthPlugin
Article • 04/30/2025
{
"name": "AuthPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "auth"
}
{
"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"
]
}
}
}
{
"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
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
ノ Expand table
ノ Expand table
in Where the parameter is expected to be found. Allowed values: header , query , Yes
cookie
ノ Expand table
Property Description Required
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
Shows a warning when Dev Proxy intercepted the same request within the specified period of
time.
{
"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
cacheThresholdSeconds The number of seconds between the same request that triggers the 5
guidance warning.
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.
{
"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
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})]"
}
]
}
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})]"
}
]
}
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"]
}
}
]
}
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
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.
ノ Expand table
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.
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
action Defines how Dev Proxy interacts with the data. Yes None
Possible values: getAll , getOne , getMany ,
create , merge , update , delete .
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
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
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.
Actions
ノ Expand table
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
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
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.
[
{
"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.
{
"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
preferredBrowser Which browser to use to launch Dev Tools. Supported values: Edge , Edge
EdgeDev , Chrome
Known issues
Next step
Inspect requests and responses using Chrome DevTools
EntraMockResponsePlugin
Article • 04/08/2024
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
{
"name": "EntraMockResponsePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "mocksPlugin"
}
Configuration example
See MockResponsePlugin
Configuration properties
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
Tip
{
"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
groupBy How proxy should group the information in the summary. Available options: url , url
messageType
--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.
{
"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
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.
-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
{
"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
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.
text
GET https://jsonplaceholder.typicode.com/posts?api-key=123
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
{
"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
maxMs The maximum amount of delay added to a request in milliseconds. Max value is 5000
10000 (10 s)
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.
{
"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
typesFilePath Path to the file that lists permissions required to call ~appFolder/config/spo-csom-
SharePoint CSOM APIs types.json
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.
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": [
]
}
}
}
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.
{
"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
apiSpecsFolderPath Relative or absolute path to the folder with API specs 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.
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.
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
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.
{
"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
apiSpecsFolderPath Relative or absolute path to the folder with API specs 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.
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
Bash
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.
{
"name": "MockGeneratorPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
}
Configuration example
None
Configuration properties
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.
{
"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
{
"$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"
}
}
}
request Defines the request that Dev Proxy should issue. Yes
ノ Expand table
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
ノ Expand table
Simulates responses.
{
"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
blockUnmockedRequests Return 502 Bad Gateway response for requests that aren't mocked false
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"
}
]
}
}
]
}
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
}
}
]
}
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"
}
]
}
}
]
}
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
}
}
}
]
}
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..."
}
}
}
]
}
Request object
Each request has the following properties:
ノ Expand table
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
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
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.
{
"name": "ODataPagingGuidancePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
}
Configuration example
None
Configuration properties
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.
{
"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.
{
"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
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
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
{
"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
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
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.
{
"name": "RetryAfterPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
}
Configuration example
None
Configuration properties
None
Next step
Simulate throttling on Microsoft 365 APIs
RewritePlugin
Article • 04/30/2025
Rewrites requests.
{
"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
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"
}
}
]
}
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
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
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
{
"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
ignoreResponseTypes Determines whether to generate types for API responses ( false ) or to false
set them to string ( true ).
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
{
"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.
{
"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
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.
{
"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
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
ノ Expand table
{
"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
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
To issue the configured notification request, press w in the command prompt session
where Dev Proxy is running.
ノ 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.
{
"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
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.
{
"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
type Determines which type of permission scopes to return. Can be Delegated or Delegated
Application
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.
{
"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
permissionsToIgnore The scopes to ignore and not include in the profile openid offline_access
report. email
Next step
Check if you're using excessive Microsoft Graph API permissions
GraphMockResponsePlugin
Article • 04/08/2024
{
"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
{
"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
allowedErrors List of HTTP status codes that Dev Proxy might produce. 429 500 502 503
504 507
-a, --allowed-errors List of HTTP status codes that Dev Proxy might 429 500 502 503
produce. 504 507
Tip
ノ 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.
{
"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
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.
{
"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.
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}
{
"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
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
{
"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
{
"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
{
"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
Usage
Console
devproxy
Arguments
None
Options
ノ Expand table
-e, --env <env> Variables to set for the Dev string key1=value n/a
Proxy process
-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/*"
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
Arguments
None
Options
ノ Expand table
Usage
Console
Arguments
ノ Expand table
Tip
Each sample lists its ID in the details section on the sample page in the Sample
Solution Gallery.
Options
ノ Expand table
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
Arguments
ノ Expand table
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
Arguments
None
Options
ノ Expand table
Usage
Console
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
Console
Arguments
None
Options
ノ Expand table
-n, --name The name of the user to create string Dev Proxy
the token for.
audience.
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
Usage
Console
devproxy msgraphdb
Arguments
None
Options
ノ Expand table
Name Description Allowed values Default
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