_private/qwestly-docs/Engineering/api-python-internal-services.md

Internal and shared services in api-python

New APIs and backing services that are not specific to the Candidate or Hire Next.js apps belong in api-python.

Examples (non-exhaustive)

  • LLM-backed evaluations (starting with interview evals; expected to cover other evaluation types later)
  • Third-party LinkedIn profile resolution helpers
  • Email sending
  • Webhooks and other integrations that multiple callers share

Treat api-python as the default home for cross-app plumbing; keep endpoints in Candidate or Hire when they are tightly coupled to that appโ€™s UX, cookies, or product contract.


Internal routes (API key)

Protected / internal HTTP routes are organized under:

api/routes/internal

They require API key authentication.

Item Convention
Environment variable QWESTLY_SERVICE_API_KEY (shared across projects; expose it wherever server-side callers need it)
Production URL shape https://api.qwestly.com/api/internal/...
Callers Server-side requests must present QWESTLY_SERVICE_API_KEY using the header or scheme implemented in api-python (keep this doc and the repo in sync when that choice changes).

Anything that must only run from trusted backends (jobs, hires app server, candidates app server, workers) should live under /api/internal and require this keyโ€”not only โ€œfolder layoutโ€ but routing aligned with /api/internal/ as deployed.


Public or browser-facing routes

Routes that do not require the internal API keyโ€”often endpoints that must work from the browserโ€”do not need to live under api/routes/internal.

Example class: wrappers around third-party lookups (for example RapidAPI LinkedIn company or user lookup) where the client is a web app, not a held secret.

For those routes, restrict callers using a Referer allowlist (implementation should match these patterns reliably, including preview and local dev):

  • https://*.qwestly.com
  • https://*.qwestly.co
  • https://*-qwestly.vercel.app
  • http://localhost* (and treat local dev variants as equivalent to localhost per implementation)

Unauthorized referrers should be rejected before doing work.


Database: qwestly_internal

Use MongoDB database qwestly_internal for collections that back these internal, cross-application workloads (eval artifacts, webhook state, shared integration records, etc.).

Application-specific data that belongs to Candidate or Hire product domains should stay in those appsโ€™ existing databases unless there is a deliberate cross-app reason to centralize it here.


Document owner: Engineering
Last updated: May 1, 2026