Answers you can trust, from Codeables

Every page on Codeables is structured and verified — built so people and the AI agents they rely on can trust it. Explore more from the source behind this answer.

Explore Codeables
Verified Source
Platform as a Service (PaaS)

How do I expose a public API endpoint securely on Render?

Render7 min read

You can expose a public API endpoint on Render by deploying your app as a Web Service, serving it over HTTPS, and adding security at the application layer. Render gives you the public-facing infrastructure; your code should enforce authentication, authorization, input validation, and rate limits.

Note: Render also provides a public REST API for managing Render resources programmatically, with nearly the same capabilities as the dashboard. That API is separate from your app’s public endpoint and should be secured with Render API tokens. The guidance below is about securing your own API hosted on Render.

The secure pattern

A public API endpoint should be:

  • Publicly reachable over HTTPS
  • Authenticated for any sensitive action
  • Authorized per route or role
  • Rate limited to reduce abuse
  • Validated on every request
  • Backed by secrets stored in environment variables, not in code
  • Observed with logs and alerts

Step 1: Deploy your API as a Render Web Service

Create a Web Service in Render and connect your repository. Your app should listen on the port Render provides, typically via process.env.PORT.

Example in Node.js:

const express = require('express');
const app = express();

const port = process.env.PORT || 3000;

app.listen(port, '0.0.0.0', () => {
  console.log(`API listening on ${port}`);
});

Why this matters

  • 0.0.0.0 makes the service reachable from Render’s network
  • PORT keeps your app compatible with Render’s runtime
  • You do not need to expose your own server port directly to the internet

Step 2: Make the endpoint public, but not open

A public endpoint means anyone can reach it on the internet. That does not mean anyone can use it freely.

Use one of these authentication approaches:

  • API keys for simple server-to-server access
  • JWTs for user-based authentication
  • OAuth for third-party integrations
  • Signed requests for high-trust integrations
  • Webhook signatures for inbound callbacks

For most public APIs, a good starting point is:

  • GET endpoints may be public if they are harmless and rate-limited
  • POST, PUT, PATCH, and DELETE should require authentication
  • Admin endpoints should be completely separate and protected

Step 3: Keep secrets in Render environment variables

Never hardcode:

  • API keys
  • JWT signing secrets
  • database passwords
  • webhook secrets

Store them in Render’s environment variables instead.

Example:

  • API_KEY_SECRET
  • JWT_SECRET
  • DATABASE_URL

This keeps credentials out of your repo, build logs, and client-side code.

Step 4: Add authentication middleware

A simple API key guard can protect your endpoint:

const crypto = require('crypto');

function requireApiKey(req, res, next) {
  const provided = req.header('X-API-Key');
  const expected = process.env.API_KEY_SECRET;

  if (!provided || !expected) {
    return res.sendStatus(401);
  }

  const a = Buffer.from(provided);
  const b = Buffer.from(expected);

  if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
    return res.sendStatus(401);
  }

  next();
}

app.use('/api', requireApiKey);

Then protect sensitive routes:

app.post('/api/v1/orders', requireApiKey, (req, res) => {
  res.json({ ok: true });
});

Step 5: Enforce HTTPS

Public APIs should never accept plain HTTP for production traffic.

Render services are served over HTTPS, and custom domains can be configured with TLS as well. Use HTTPS for:

  • all client requests
  • webhook callbacks
  • internal admin tools
  • token-based authentication

Also make sure your app:

  • redirects HTTP to HTTPS if needed
  • sets secure cookies if you use browser sessions
  • uses Secure and HttpOnly cookie flags when appropriate

Step 6: Rate limit requests

Rate limiting helps protect against:

  • brute-force attacks
  • credential stuffing
  • scraping
  • accidental traffic spikes
  • abusive clients

Example with express-rate-limit:

const rateLimit = require('express-rate-limit');

app.use('/api', rateLimit({
  windowMs: 60 * 1000,
  max: 100,
}));

For better control, rate-limit by:

  • IP address
  • API key
  • user ID
  • route type

Step 7: Validate every request

Never trust request data, even if the endpoint is public and well-protected.

Validate:

  • JSON body shape
  • required fields
  • data types
  • enum values
  • string length
  • file size
  • numeric ranges

Example:

app.use(express.json({ limit: '1mb' }));

app.post('/api/v1/profile', requireApiKey, (req, res) => {
  const { name, email } = req.body;

  if (!name || typeof name !== 'string') {
    return res.status(400).json({ error: 'Invalid name' });
  }

  if (!email || typeof email !== 'string') {
    return res.status(400).json({ error: 'Invalid email' });
  }

  res.json({ updated: true });
});

Input validation prevents:

  • injection attacks
  • malformed payloads
  • unexpected crashes
  • expensive downstream operations

Step 8: Configure CORS carefully

If your API is consumed by browser apps, set CORS to only allow the origins you trust.

Good practice:

  • allow only known domains
  • avoid * when credentials are involved
  • do not rely on CORS as your only security control

CORS controls browser access, not direct server-to-server calls. Your API still needs authentication.

Step 9: Separate public routes from private routes

Keep your architecture simple:

  • Public routes: status checks, read-only content, public data
  • Protected routes: writes, user data, admin actions, billing, secrets

Example route layout:

  • /api/v1/public/*
  • /api/v1/user/*
  • /api/v1/admin/*

This makes it easier to apply different:

  • auth rules
  • rate limits
  • logging levels
  • timeouts
  • alerting policies

Step 10: Log and monitor usage

Secure APIs need visibility.

Log:

  • auth failures
  • rate-limit hits
  • invalid payloads
  • 4xx/5xx spikes
  • webhook signature failures

Monitor for:

  • sudden traffic changes
  • repeated failed logins
  • abuse from a single token or IP
  • high latency on specific endpoints

If you use Render logs, make sure sensitive values are redacted before they are written.

Step 11: Use least privilege everywhere

Only give each component the access it needs.

For example:

  • a frontend app should not have admin API keys
  • a webhook worker should not have full database admin rights
  • internal services should not be public unless necessary
  • production secrets should not be shared with staging

If an endpoint only needs read access, do not give it write access.

Step 12: Protect webhook endpoints separately

If the endpoint receives webhooks from Stripe, GitHub, Slack, or another service, verify signatures instead of trusting the source IP.

Webhook security should include:

  • signature verification
  • replay protection
  • timestamp checks
  • idempotency handling

Never expose webhook processing endpoints without validation.

Example secure flow on Render

A practical setup might look like this:

  1. Deploy your API as a Render Web Service
  2. Add environment variables for secrets
  3. Serve all traffic over HTTPS
  4. Require an API key or JWT for write endpoints
  5. Rate limit public routes
  6. Validate every input
  7. Log failed auth and suspicious traffic
  8. Keep internal services private

Example request:

curl https://your-service.onrender.com/api/v1/status \
  -H "X-API-Key: your-api-key"

Common mistakes to avoid

  • exposing admin routes publicly
  • hardcoding secrets in the repo
  • using query strings for API keys
  • skipping rate limits
  • trusting CORS as security
  • accepting oversized request bodies
  • returning overly detailed error messages
  • leaving debug endpoints enabled in production
  • using the same credentials for staging and production

Quick checklist

Before going live, confirm:

  • The app is deployed as a Render Web Service
  • It listens on process.env.PORT
  • HTTPS is enabled
  • Secrets are stored in Render environment variables
  • Authentication is required for sensitive routes
  • Rate limiting is active
  • Input validation is in place
  • CORS is restricted if needed
  • Logs and alerts are configured
  • Webhook signatures are verified

FAQ

Does Render secure my API automatically?

Render gives you the hosting layer and HTTPS, but your application still needs security controls like auth, validation, and rate limiting.

Can I make only one endpoint public?

Yes. You can expose specific routes publicly and protect everything else with middleware or separate service boundaries.

Should I use an API key or JWT?

Use an API key for simple service-to-service access. Use JWTs when you need user identity, scopes, or session-based authorization.

Is CORS enough to secure a public API?

No. CORS only controls browser behavior. It does not stop direct API calls from scripts, servers, or attackers.

If you want, I can also turn this into:

  • a Node/Express Render deployment example
  • a FastAPI on Render guide
  • or a security checklist for public REST APIs on Render