Skip to main content
Your app can answer requests on the merchant’s own storefront, at https://<store-domain>/apps/<slug>/<rest>, without the merchant editing their theme. Salesive forwards the request to your app’s proxyUrl and returns your app’s answer to the shopper. That is how an app serves a booking form, a product finder or a small JSON endpoint on the store’s own domain. The /apps prefix is reserved: a request under it with no active installation of a matching app is a plain 404, never the storefront’s page.
This is the storefront, not the dashboard. /apps on app.salesive.com is the dashboard’s own route and has nothing to do with this proxy.

How a request flows

  1. A shopper opens https://shop.example.com/apps/reviews/stars?product=123.
  2. Salesive finds the active installation of the app whose slug is reviews on that store.
  3. It builds https://apps.example.com/reviews/stars?product=123 from the app’s proxyUrl (https://apps.example.com/reviews), the rest of the path and the query string, and sends a GET to it.
  4. Your app answers. Salesive passes the status, the content type and the body back to the shopper.

Set the proxy URL

proxyUrl is an optional HTTPS base URL on your app. In the developer console, open your app, go to the Configuration tab, choose Production, and fill App proxy URL. After you save it, the console shows a copyable example URL on your current store so you can check the path. You can also send it with the app update endpoint, using your merchant session:
  • The base path is kept. https://apps.example.com/reviews plus /stars becomes https://apps.example.com/reviews/stars.
  • A query string already on the proxy URL is kept, and the incoming query is appended after it.
  • Send "" or null to remove it.
  • The URL must be HTTPS, must not contain credentials, and must not resolve to a private, loopback or link local address. Salesive checks it with the same guard as a webhook URL when you save it.
  • One URL serves every install, unless a release pins a different one.

Releases and development installs

proxyUrl is part of the release snapshot, next to the webhook URL and signing secret. An install pinned to a release keeps that release’s proxy URL and secret, even after you edit the app. Publishing a release writes its snapshot back onto the app for consumers that do not read releases. There is no development proxy URL. A development install uses the same proxyUrl and the production signing secret, so point it at a public HTTPS host while you test (a tunnel works), not at your machine.

What your app receives

Methods

Only GET and POST. Any other method is 405 with Allow: GET, POST.

URL

Your proxyUrl base path, the rest of the path, and the shopper’s query string. Dot segments (. and ..) in the path are refused, so a request cannot walk out of your base path.

Headers

The only headers forwarded from the shopper are Content-Type, Accept and User-Agent. Everything else stays on the storefront. In particular, your app never receives the shopper’s Cookie, Authorization, Referer, IP address or any X-Forwarded-* header.
The app cannot see the shopper’s session, and it cannot set a cookie either: Set-Cookie is not forwarded back. Every proxy request is anonymous apart from the store and app identity in the signed headers. If a page needs to know who the shopper is, have the theme or an app block pass a token in the query or body, or keep the state in your own backend.

Body

A POST body is forwarded as the exact bytes received, with the Content-Type the shopper sent. Any content type is accepted. The body limit is 5 MB; a larger body is 413.

Verify the signature

The proxy is signed with your app’s webhook signing secret, using the same construction as webhook signature v2: base64 HMAC-SHA256 of <t>.<raw body>, in X-Salesive-Signature: t=<unix seconds>,v1=<signature>.
  • Verify the raw bytes before parsing.
  • Reject a t more than 300 seconds from your clock, in either direction.
  • A GET has an empty body, so the signed string is <t>. followed by nothing.
Node.js (Express)
The signature covers the timestamp and the body, not the path or the query string. Treat it as proof that the request came through Salesive for this store and app, and still decide for yourself what a given path or argument may do.

What your app returns

  • The status code and the Content-Type pass through. The body is not rewritten. If your app sends no content type, the response is application/octet-stream.
  • Only Content-Type is taken from your response headers. Your app cannot set cookies or custom headers on the storefront response.
  • Every response, including errors, is Cache-Control: private, no-store and X-Content-Type-Options: nosniff.
  • A 3xx is refused. Salesive answers 502 rather than following a redirect the shopper never sees.
  • A response over 5 MB is 502.
  • Your app has 10 seconds to answer, body included. A timeout is 504.
  • An unreachable app is 502.
Responses are buffered before they reach the shopper, so a streaming response (server-sent events, a long download) arrives only when it is complete. WebSockets are not proxied.

Limits and errors

Error bodies are plain text. The storefront limits each store and app pair to a burst of 120 requests and a sustained 2 requests a second, and answers 429 when the bucket is empty. The bucket is per storefront instance, so two instances allow twice the burst.

Uninstall and suspend

The proxy needs an active installation of an active app. When the merchant uninstalls your app, or the app is suspended, the next request under /apps is 404. Nothing is cached, so there is no window where an old answer is served.

Security notes

  • The request comes from Salesive’s storefront servers, not from the shopper’s browser. Your endpoint must be reachable from the public internet over HTTPS.
  • The signed headers are the only trusted identity. Your endpoint is also reachable outside the proxy, so never trust a header a caller could set itself.
  • The proxy carries no app token and no scopes. If you need store data, call the Apps API with your own app token, the same as any other request.
  • Treat the path, query and body as untrusted shopper input.

Next steps

Storefront extensions

Scripts, app embeds and app blocks that run inside the storefront page.

Webhooks

The same signature construction, for events Salesive sends to you.

Releases

Pin installs to the proxy URL and secret a release was tested with.