Reference implementation for ESS API platform integration.
The full functional API documentation for the ESS platform is available at api-docs.rr-wfm.com/docs/ess. Consult it for endpoint specifications, request/response schemas, and webhook event types.
- Bun 1.3 or later: https://bun.sh
- Access to an R&R ESS environment
- OAuth client credentials from R&R support
If you do not have credentials yet, send a request to support@rr-wfm.com.
Include the following information in your request:
- Intended redirect URI(s), for example:
http://localhost:5173/auth/callback - Contact email address(es) for the integration
- Whether you want to request an account for the R&R JobApp as well
Create a .env file in this folder based on .env.example.
IDP_URL=https://ess.gat.rr-wfm.com/identity
IDP_CLIENT_ID=your-client-id
IDP_CLIENT_SECRET=your-client-secret
IDP_SCOPE=openid ess offline_access
IDP_ACR_VALUES=
IDP_REDIRECT_URI=http://localhost:5173/auth/callback
ESS_BASE_URL=https://ess.gat.rr-wfm.com
BUN_SERVER_PORT=3001
WEBHOOK_API_KEY=replace-with-long-random-secretRequired values:
IDP_URLIDP_CLIENT_IDIDP_CLIENT_SECRETESS_BASE_URLWEBHOOK_API_KEY
Important:
- Keep
offline_accessinIDP_SCOPEso refresh tokens are issued. IDP_REDIRECT_URImust match the redirect URI registered for your client. The redirect uri for this reference app is by defaulthttp://localhost:5173/auth/callbackscope.uriin webhook test payloads must use the same host asESS_BASE_URL.- Use a long random value for
WEBHOOK_API_KEY. This value is required asAuthorization: <WEBHOOK_API_KEY>when callingPOST /api/webhook/v1/receive. IDP_ACR_VALUESis optional. When set, the value is forwarded as theacr_valuesparameter in the OpenID Connect authorization request sent to the R&R identity provider. IdentityServer treatsacr_valuesas additional authentication context — it can be used, for example, to trigger a specific authentication method or to pass a tenant hint for your external identity provider. Leave it empty unless R&R has provided specific values for your integration.
In order to start the application, run the following commands:
bun install
bun run startThis starts:
- Frontend (Vite):
http://localhost:5173 - Local Bun API/proxy server:
http://localhost:3001
- Open
http://localhost:5173 - Click Login
- Complete sign-in with the credentials for the R&R JobApp.
When configured by R&R, you can use acr_values to perform the sign in on your external identityprovider
- Confirm the app loads modules/schedule data
Quick health check:
curl http://localhost:3001/api/healthExpected response:
{
"ok": true
}Before ESS will deliver webhook events to your endpoint, you must enroll each worker you want to track. Your integration's notification scope is bounded by the R&R customer it was set up for — you will only ever receive notifications for workers within that customer's scope, as determined by the credentials issued to you. Within that scope, notifications are opt-in per worker: you must explicitly subscribe each worker to activate delivery.
To enroll a worker, send a POST request while authenticated (the app will attach your access token automatically):
curl -X POST http://localhost:3001/api/ess/webhook/v1/subscribe \
-H "Content-Type: application/json" \
--cookie "ess.session=<your-session-cookie>"The server forwards the request to the ESS API at {ESS_BASE_URL}/webhook/v1/subscribe. Consult the ESS API documentation for the required body fields (such as worker identifiers and the webhook URL to register).
You must be signed in before calling this endpoint. The session cookie is set automatically by the browser after login; for curl testing, copy it from your browser's developer tools.
Use this to simulate webhook delivery during local development.
- Create a new request in Postman
- Method:
POST - URL:
http://localhost:3001/api/webhook/v1/receive - Headers:
Content-Type: application/jsonAuthorization: <WEBHOOK_API_KEY>
- Body type:
raw->JSON - Use payload:
{
"events": [
{
"scope": {
"workerId": "GREEN10-67890",
"uri": "https://ess.gat.rr-wfm.com/scheduling/v1/GREEN10-67890",
"period": {
"from": "2024-01-01",
"until": "2024-01-07"
}
},
"event": {
"timestamp": "2024-01-01T12:00:00Z",
"type": "schedule",
"action": "finalized"
}
}
]
}Or use curl:
curl -X POST http://localhost:3001/api/webhook/v1/receive \
-H "Content-Type: application/json" \
-H "Authorization: <WEBHOOK_API_KEY>" \
-d '{
"events": [
{
"scope": {
"workerId": "GREEN10-67890",
"uri": "https://ess.gat.rr-wfm.com/scheduling/v1/GREEN10-67890",
"period": {"from": "2024-01-01", "until": "2024-01-07"}
},
"event": {
"timestamp": "2024-01-01T12:00:00Z",
"type": "schedule",
"action": "finalized"
}
}
]
}'- Click Send
Use this when ESS or another remote sender must deliver webhook payloads to your local machine.
- Start the app locally (
bun run start) so the API listens onhttp://localhost:3001. - Start a tunnel to the API port:
ngrok http 3001- Copy the HTTPS forwarding URL from ngrok, for example
https://rr-example.ngrok-free.app. - Add a webhook with the following URL for the client in R&R:
https://rr-example.ngrok-free.app/api/webhook/v1/receive
- Include header:
Authorization: <WEBHOOK_API_KEY>
- Start the app locally (
bun run start) so the API listens onhttp://localhost:3001. - Create and start a tunnel:
devtunnel host -a -p 3001- Copy the generated HTTPS URL.
- Add a webhook with the following URL for the client in R&R:
https://<your-devtunnel-host>/api/webhook/v1/receive
- Include header:
Authorization: <WEBHOOK_API_KEY>
Notes:
- Keep the tunnel process running while testing.
- For production-like testing, rotate
WEBHOOK_API_KEYregularly and never share it publicly.
Expected response:
{
"received": 1
}Verify stored events:
curl http://localhost:3001/api/webhook/v1/eventsinvalid_clientduring login:- Verify
IDP_CLIENT_IDandIDP_CLIENT_SECRET.
- Verify
invalid_grantduring token exchange:- Start login again and complete it quickly; authorization codes are one-time and short-lived.
Failed to load openid configuration (403)fromGET /api/auth/config:- Your IdP may block
.well-known/openid-configurationfrom your network. - For R&R, these are usually
<IDP_URL>/connect/authorizeand<IDP_URL>/connect/token.
- Your IdP may block
- App cannot fetch ESS data:
- Verify
ESS_BASE_URLand ensure webhook payloadscope.uriuses the same ESS host.
- Verify
- Port
3001already in use:- Stop the process using that port or set
BUN_SERVER_PORTto a different value.
- Stop the process using that port or set
- After restarting the Bun server, the browser shows
No active sessionor401errors:- Sessions are stored in memory and are lost when the server restarts. Clear localStorage (
ess.app.session) and theess.sessioncookie in the browser, then log in again.
- Sessions are stored in memory and are lost when the server restarts. Clear localStorage (
GET /api/healthGET /api/auth/configPOST /api/auth/tokenPOST /api/ess/webhook/v1/subscribe— enroll workers in your webhook subscription; proxied to the ESS API with your access tokenGET /api/ess/modules/v1/{workerId}GET /api/ess/scheduling/v1/{workerId}POST /api/ess/by-uri— fetch any ESS resource by its full URI ({ "uri": "<ess-url>" }); used after receiving a webhook to load updated data without triggering browser CORS restrictionsPOST /api/webhook/v1/receiveGET /api/webhook/v1/events