Pro App Web Requests
Web requests let a Pro app talk to external services — a courier API, a payment provider, a partner system — without ever holding the credentials or even knowing the address it calls.
You define the request once, in the backend. The running app calls it by name and passes a few parameters. Everything else — the address, the headers, the body, the credentials — stays on the server.
How it works
App → "call acme.getOrder with orderId = SO-1042"
↓ (backend adds address, headers, credentials)
https://api.acme.com/v2/orders/SO-1042
↓
App ← the response
The app cannot change where the call goes. Parameters can only fill in the places you allowed, so a request can never be pointed at a different service.
Enabling web requests
- Open the app in the App Builder.
- Switch to the Backend tab.
- Select Web Requests from the left menu.
- Turn on the section.
Web requests require a Pro app. Only users with Design access can define or change them; anyone who can run the app can call an enabled request.
Defining a request
Click Add request and fill in:
- Name — how the app refers to it, for example
acme.getOrder. - Title and description — what it does, in plain words.
- Method —
GET,POST,PUT,PATCHorDELETE. - Address — the target address, with placeholders where parameters go, for example
https://api.acme.com/v2/orders/{{param.orderId}}. - Parameters — the values the app is allowed to supply: name, type, whether they are required, and an optional default.
- Headers and body template — fixed values, with the same placeholders available.
- Authentication — see below.
- Enabled — turn a request off without deleting it.
Press Test to run the request from the backend and see the response with all credentials redacted.
Authentication
Credentials always come from secrets — you reference the secret by name, never by value.
| Option | What it does |
|---|---|
| None | The service needs no credentials. |
| Bearer token from a secret | Sends a bearer token taken from a secret. |
| Basic auth from secrets | Sends a user name and password taken from two secrets. |
| OAuth2 client credentials | The backend logs in with a client id and secret, gets an access token, and uses it. |
With OAuth2 client credentials the backend handles the whole login for you: it fetches the token, keeps it until shortly before it expires, reuses it for every call, and renews it automatically. Tokens are kept separately for each set of credentials, so two requests with different credentials never share a token.
Using it in an app
Just describe what the app should do — the App Builder wires the call in for you:
When the user picks an order, fetch it from Acme and show the delivery status.
Add a button that pushes the selected document to the partner system.
Which web requests can this app call?
The app receives the status code and the response content. If the request is disabled, a parameter is missing, a secret has no value, or the external service fails, the app gets a clear message explaining what went wrong.
What the app gets back
A call always returns a small wrapper around the answer — the status of the call plus the content:
{ status: 200, data: <the service's answer> }
The answer itself is always under data. For an ERP.net list that means the rows are result.data.value. If anything goes wrong, the call fails with a readable message instead of returning an error object, so app code wraps it in a try/catch.
try {
const res = await operator.requests.call('catalog.products', { top: 60 });
const payload = res.data ?? res; // tolerant unwrapping
const rows = Array.isArray(payload.value) ? payload.value : [];
} catch (err) {
showError(err.message);
}
The Test button in the backend shows the same content: what appears under data there is exactly what the running app receives.
The App Builder can create, change, test, mark public and delete these requests for you — you only need to enter the credential values yourself under Secrets.
Public requests (for public pages)
A visitor of a public page is not signed in, so the app cannot use that visitor's ERP.net connection, backend tables, stored files or secret values. The supported way to show server data on a public page is a request marked Public.
A public request:
- can be called by anyone visiting a published public page of the app;
- runs entirely on the server with its own stored credentials — typically a service account or client id / secret;
- never receives the visitor's identity, and never exposes the credentials to the browser.
This also covers ERP.net: point the request at the ERP.net Domain API address, give it a service login stored in secrets, and the public page can show the data without anyone signing in.
Example — a public product catalog:
Address: https://<instance>/api/domain/odata/General_Products_Products?$filter=Active eq true and ShowInCatalog eq true&$top={{param.top}}
Auth: OAuth2 client credentials (client id and secret from Secrets)
Public: yes
Keep public requests as narrow as possible: bake the filters into the address and expose only harmless parameters such as paging or a search term. Anyone with the link can call a public request.
Safety limits
- Only
httpsaddresses; internal and local network addresses are refused. - Redirects to another host are not followed.
- Response size and duration are capped, so a slow service cannot block the app.
- Sensitive response headers never reach the app.
- Per-app and per-user rate limits apply.
- Logs record which request ran and which credential scope was used — never the credential itself.