Build a customer website with the API
Turn a scoped WinLayer credential into a branded opportunity and pipeline portal without exposing the key to the browser.
Complete runnable example: the repository includes the standalone Northstar Growth Portal, with no runtime dependencies.
What the example proves
- A customer can present WinLayer intelligence under its own product and visual identity.
- The API key stays in the customer's server environment and never reaches HTML, JavaScript, cookies, local storage, or URLs.
- Scored opportunities, pursuit decisions, forecasts, agency records, and subscription usage come from real public API endpoints.
- A sandbox key returns deterministic synthetic records; replacing it with a live key switches the same website to tenant data.
1. Create a least-privilege API key
Open Developer → Credentials, choose Sandbox, and grant only workspace:read, opportunities:read, pipeline:read, forecasts:read, agencies:read, and usage:read.
2. Keep the secret on the server
const API_URL = process.env.WINLAYER_API_URL;
const API_KEY = process.env.WINLAYER_API_KEY;
async function winlayer(path) {
const response = await fetch(new URL(path, API_URL), {
headers: {
accept: "application/json",
authorization: `Bearer ${API_KEY}`,
},
cache: "no-store",
});
if (!response.ok) throw new Error(`WinLayer returned ${response.status}`);
return response.json();
}The browser requests the customer's page. The customer's server requests WinLayer. Never put WINLAYER_API_KEY in a public build variable or client component.
3. Compose the customer experience
const [identity, opportunities, pipeline, forecasts, agencies, usage] =
await Promise.all([
winlayer("/api/v1/public/whoami"),
winlayer("/api/v1/public/opportunities?limit=8&min=40"),
winlayer("/api/v1/public/pipeline?limit=8"),
winlayer("/api/v1/public/forecasts?limit=8"),
winlayer("/api/v1/public/agencies?limit=8"),
winlayer("/api/v1/public/usage"),
]);Render only the fields the customer's users need: contract title, agency, fit, PWin, recommendation, deadline, pursuit status, forecast confidence, and business-capacity usage.
4. Run the supplied website
cd examples/customer-api-site
WINLAYER_API_URL=https://api.winlayer.ai \
WINLAYER_API_KEY='wl_test_your_reveal_once_key' \
WINLAYER_CONSOLE_URL=https://winlayer.ai/developer#credentials \
PORT=4300 \
node server.mjsBefore a real customer launch
- Store the key in the hosting platform's encrypted secret manager.
- Add the customer's own login and authorization boundary around the portal.
- Use one scoped credential per deployed system and rotate it without downtime.
- Honor
429andRetry-After; cache non-urgent reads on the customer server. - Revoke a leaked or retired credential immediately in the Developer Portal.
Next: review rate limits and signed webhooks before adding background synchronization.