Developers

    Express Example: Create a UPCS Embed Session

    An Express.js route that creates a UPCS embed session with fetch, rate limits itself and returns only the session token to the browser.

    Updated 14 October 2026 · 2 min read

    This Express example adds one route, GET /upcs-session, that your front end calls before mounting the map. It builds on the plain function in create an embed session in Node.js.

    The server

    import express from 'express';
    
    const app = express();
    const UPCS_BASE = 'https://api.upcs.io/api';
    const ORIGIN = process.env.UPCS_ORIGIN || 'https://shop.example.com';
    
    // Tiny in-memory limiter: max 30 calls per minute per IP.
    const hits = new Map();
    function limit(req, res, next) {
      const now = Date.now();
      const entry = hits.get(req.ip) || { count: 0, start: now };
      if (now - entry.start > 60_000) { entry.count = 0; entry.start = now; }
      entry.count += 1;
      hits.set(req.ip, entry);
      if (entry.count > 30) return res.status(429).json({ error: 'Too many requests' });
      next();
    }
    
    app.get('/upcs-session', limit, async (req, res) => {
      try {
        const r = await fetch(`${UPCS_BASE}/v1/embed/sessions`, {
          method: 'POST',
          headers: {
            'x-api-key': process.env.UPCS_API_KEY,
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({ origin: ORIGIN }),
        });
        const data = await r.json();
    
        if (!r.ok || data.success === false) {
          console.warn('UPCS error', r.status, data.code);
          return res.status(502).json({ error: 'Map unavailable' });
        }
        res.json({ session_token: data.session_token, expires_at: data.expires_at });
      } catch (e) {
        console.error('UPCS request failed', e);
        res.status(502).json({ error: 'Map unavailable' });
      }
    });
    
    app.use(express.static('public'));
    app.listen(3000);
    

    Why these choices

    • The origin comes from configuration, so clients cannot choose it. It must match an entry under allowed origins.
    • Upstream details are logged on the server and hidden from visitors.
    • The limiter keeps your endpoint from burning the key's hourly limit; production setups usually use a shared store rather than process memory. See rate limits and backoff.

    Behind a proxy

    If Express sits behind a load balancer, configure trust proxy so req.ip is the visitor, not the proxy.

    Next

    Mount the map on your page using UPCS.mount options explained, and keep the key safe as described in securing your UPCS API key.

    Frequently asked questions

    Which Node.js version do I need?

    Node 18 or later has fetch built in. On older versions use a fetch-compatible HTTP client.

    Do I need express-rate-limit?

    It is not required, but limiting your own endpoint prevents visitors from using up the key's hourly allowance.