# Make your backend Sage-compatible

> Allow the backend in Sage, configure CORS, and verify both sides of the connection.

A backend request from an installed Sage app passes through two independent gates. Sage’s network policy decides whether the frontend may connect, then your backend’s CORS policy decides whether the browser may expose the response. Configure and test both before adding wallet features.

## Allow the backend in the manifest

Add every remote origin the installed frontend needs to `permissions.network.whitelist`. Use `required` when the app cannot work without that service. Use `optional` only when the app has a useful fallback if the user declines it.

Sage accepts `https` and `wss` origins. Declare the origin only—scheme, host, and optional port—with no path. You do not need a bridge capability just to call your own backend.

**Add to sage-manifest.json**

```json
{
  "permissions": {
    "network": {
      "whitelist": {
        "required": ["https://api.example.com"]
      }
    }
  }
}
```

## Calculate the installed app origin

Sage normalizes the installation URL by removing its query and fragment and ensuring the path ends with `/`. It calculates the SHA-256 hash of that complete normalized URL, takes the first 16 hexadecimal characters, and combines them with a slug of the hostname to produce an identity such as `url-xch-place-4c641f547d3d7923`.

Each installation adds a UUID to that stable identity. The app runs as `sage-app://{uuid}.{identity}` on macOS and Linux, and as `https://sage-app.{uuid}.{identity}` on Windows. Use the calculator below to generate one CORS regex that recognizes both forms for your app URL.

Use this regex in your backend’s CORS origin matcher. It does not belong in the Sage manifest—the manifest’s network whitelist contains the backend origin the frontend calls.

## Choose the right CORS policy

The installed app does not run at your public website’s origin, so allowing only that website will not cover Sage. Match the generated cross-platform pattern alongside the ordinary production and development origins your backend already trusts.

For an API that does not use browser cookies or other credentialed requests, `Access-Control-Allow-Origin: *` is the simplest compatible response. It is not authentication: continue to protect private operations with tokens or signatures. If the API uses browser credentials, validate the incoming origin, echo only an allowed value, return `Access-Control-Allow-Credentials: true`, and add `Vary: Origin`.

- Keep existing production and local-development web origins working
- Treat CORS as a browser boundary, not authorization
- Apply the same policy to success and error responses

## Answer preflight before authentication

Requests with JSON, authorization headers, or non-simple methods usually trigger an `OPTIONS` preflight. Handle it before authentication middleware rejects the request. Return the allowed origin, methods, and every request header the frontend actually sends.

A successful preflight normally has no response body. Cache it only for a duration that lets you change the policy safely.

- Return `Access-Control-Allow-Methods` for the methods you support
- Return `Access-Control-Allow-Headers` for headers such as `Content-Type` and `Authorization`
- Return a successful status for `OPTIONS` without running the application handler

## Test both gates

Rebuild and update the Sage app after changing its manifest, then test the real installed app against the deployed backend. A `connect-src` console error points to the Sage network permission. A CORS or preflight error means the request reached the browser’s CORS boundary and the backend response needs attention.

Verify a normal response, an authenticated response, a backend error, and a preflight. Then repeat the ordinary web version to make sure Sage compatibility did not break existing users.

## Builder's note

Bridge APIs and client behavior can evolve. Verify implementation details against the Sage version you support, then test in both Sage and a normal browser.

---

Human-readable page: https://fancybudgie.com/sage/guides/cors-for-sage-apps

Guide index: [llms.txt](https://fancybudgie.com/llms.txt)
