_private/qwestly-docs/Engineering/api-python-internal-services.md
Table of Contents
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.comhttps://*.qwestly.cohttps://*-qwestly.vercel.apphttp://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