Static Outbound IP for Dynamics 365 Finance & Operations API Integrations

QuotaGuard Engineering
March 8, 2026
5 min read
Pattern

Static Outbound IP for Dynamics 365 Finance & Operations API Integrations

D365 Finance & Operations doesn't have a static outbound IP. Microsoft says so directly: the specific outbound IP address may vary across requests, even within the same session. If you've allowlisted your dev VM's IP and your integration works fine in Dev but breaks in UAT and Production, this is why. The fix is routing your outbound calls through an HTTP proxy with a fixed IP, set explicitly in X++ code. This post shows you how.

Why D365 FO Can't Give You a Static Egress IP

The cloud-hosted AOS runs on Microsoft-managed Azure infrastructure. You don't own the VMs. You can't edit machine.config, configure OS-level networking, or set HTTP_PROXY environment variables at the system level. The outbound IP comes from the PowerPlatformPlex Azure service tag for your deployment region, and it shifts without notice.

The common answer on the forums is "allowlist Microsoft's IP ranges from the Azure JSON file." I've seen that suggestion. It's not practical. Those ranges cover thousands of IPs shared across all Azure tenants in your region. Most API vendors with a firewall won't accept that, and the ones that do are creating a security problem for themselves.

The other approach that comes up is Azure Logic Apps with a NAT Gateway, or Azure API Management as an intermediary. Those work, but they add infrastructure, cost, and complexity for a problem that can be solved in about 15 minutes with a proxy and a few lines of X++.

Why This Works: D365 Runs Full .NET CLR

Unlike some serverless platforms where the runtime sandboxes your HTTP calls and blocks proxy configuration entirely, D365 runs on a full .NET CLR. That means the standard .NET proxy APIs are available in X++ through CLR interop. You can set System.Net.WebProxy directly on any outbound request. The proxy handles the CONNECT tunnel to your static IP transparently. No platform restrictions. No workarounds needed.

The one thing that won't work automatically: D365's cloud-hosted environment doesn't reliably surface Azure App Service environment variables to X++ code. So you can't just drop QUOTAGUARDSTATIC_URL in your environment and expect it to be picked up. Store the proxy URL in D365 system parameters or Azure Key Vault and read it explicitly at runtime.

The Fix: Set WebProxy in X++ Code

Here's the pattern that works for custom X++ service integrations. This covers the most common case: an outbound REST or SOAP call to an IP-restricted external API.

// Store your QuotaGuard URL in a system parameter, not hardcoded
str proxyUrl = SystemParameters::find().QuotaGuardProxyUrl;

System.Net.WebProxy proxy = new System.Net.WebProxy(proxyUrl, true);

System.Net.HttpWebRequest request =
    System.Net.WebRequest::Create(targetUrl) as System.Net.HttpWebRequest;

request.set_Proxy(proxy);
request.set_Method("GET");
request.Headers.Add("Authorization", "Bearer " + accessToken);

System.Net.HttpWebResponse response =
    request.GetResponse() as System.Net.HttpWebResponse;

System.IO.StreamReader reader =
    new System.IO.StreamReader(response.GetResponseStream());

str responseBody = reader.ReadToEnd();

The proxyUrl value is your QuotaGuard proxy URL, which looks like http://username:password@proxy.quotaguard.com:9293. You get this from your QuotaGuard dashboard after signing up. Every request routed through it exits from one of your two static IPs. Allowlist those two IPs once with the API vendor and you're done — Dev, UAT, and Production all use the same proxy, so the same two IPs work everywhere.

Cleaner Option: C# HttpClient in a D365 Extension DLL

For new integrations or anything more complex than a single request, a C# helper class gives you better async support and a cleaner separation of concerns. Deploy it as a D365 extension DLL and call it from X++.

// C# class library deployed as D365 extension
public class ProxiedHttpClient
{
    public static string Get(string targetUrl, string proxyUrl)
    {
        var handler = new HttpClientHandler
        {
            Proxy = new WebProxy(proxyUrl),
            UseProxy = true
        };

        using var client = new HttpClient(handler);
        var response = client.GetAsync(targetUrl).GetAwaiter().GetResult();
        return response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
    }
}
// Call from X++
str result = ProxiedHttpClient::Get(
    "https://api.yourvendor.com/data",
    SystemParameters::find().QuotaGuardProxyUrl
);

What About Electronic Reporting Web Service Calls

Electronic Reporting's built-in HTTP layer doesn't expose a proxy setting in the ER designer. If you're using an ER web service data source to call an IP-restricted endpoint, the built-in call won't route through the proxy. The fix there is replacing the ER web service call with a custom X++ action class that uses the explicit WebProxy pattern above, then invoking it from ER through a custom data provider.

For on-premises deployments where you own the AOS VMs, there's a simpler option: add the proxy to machine.config on each AOS node and it applies system-wide with no code changes.

<system.net>
  <defaultProxy>
    <proxy usesystemdefault="true"
           proxyaddress="http://username:password@proxy.quotaguard.com:9293"
           bypassonlocal="true" />
  </defaultProxy>
</system.net>

Two Static IPs, Works Across Every Environment

QuotaGuard provides two static IPs per account in a load-balanced pair with automated failover. You give both IPs to your API vendor to allowlist. After that, it doesn't matter what Microsoft does to the underlying Azure infrastructure — your egress identity doesn't change.

Plans start at $19/month on Micro for shared IPs. If your security team requires IPs that no other customer shares, dedicated IPs are available on the Enterprise plan at $219/month.

One thing worth considering: some API vendors with firewall restrictions also need to send callbacks or webhooks back to your D365 environment. That's an inbound traffic problem. QuotaGuard Shield handles it — it routes inbound traffic through fixed IPs so you can tell the vendor exactly which IPs to expect traffic from. If your integration is two-way, it's worth looking at alongside the outbound setup.

If you're ready to fix your D365 outbound IP problem, see plans and pricing here.

QuotaGuard Static IP Blog

Practical notes on routing cloud and AI traffic through Static IPs.

Reliability Engineered for the Modern Cloud

For over a decade, QuotaGuard has provided reliable, high-performance static IP and proxy solutions for cloud environments like Heroku, Kubernetes, and AWS.

Get the fixed identity and security your application needs today.