One of the easiest ways to lose time on browser integrations is to assume an API failure is really an API failure.

Sometimes the endpoint works. Sometimes the request payload is fine. Sometimes the browser is the only thing objecting, because the browser is enforcing a cross-origin rule the backend never intended to support directly.

That is what this note was about.

The Problem

The frontend was trying to call a third-party payment API directly from the browser.

The browser objected because of cross-origin restrictions.

The most useful line in the original note was the simplest one:

The workaround was to create a proxy between requests. So the request would look like App > proxy > payment provider.

That is the right way to think about it.

Why the Browser Fails Here

From the browser’s perspective, this is a cross-site request. If the remote API does not provide the exact CORS behavior your frontend needs, the browser blocks the request before your application logic gets what it wants.

You can reproduce parts of this with curl, but curl is not a browser. So a successful curl request does not automatically mean the frontend integration is valid.

That is the trap.

The Practical Fix

Instead of calling the payment API directly from the client:

1
Browser App -> Third-Party Payment API

route the request through your own backend or proxy:

1
Browser App -> Your Proxy -> Third-Party Payment API

That does two useful things:

  • it removes the browser-side cross-origin restriction from the critical path
  • it keeps sensitive signing or API logic off the client

Why I Like This Pattern

This is one of those notes that starts as a workaround but ends up being the better architecture anyway.

Even if the payment provider eventually offers a browser-friendly CORS policy, I usually do not want signature generation, sensitive request shaping, or provider-specific integration details living in the frontend if I can avoid it.

Closing Thought

CORS bugs often feel like networking bugs until you remember who is actually enforcing the rule. Once you see that clearly, the proxy pattern stops looking like a hack and starts looking like the correct boundary.