Full API Proxy Server (Python)
If your frontend JavaScript needs to call Qarta API endpoints, you must route those requests through a server-side proxy. Embedding your API key in browser code exposes it to anyone who views your page source or network traffic.
The proxy in this guide forwards any HTTP method to any Qarta endpoint, adding the Authorization header server-side. Your frontend makes unauthenticated requests to the proxy; the proxy authenticates and forwards them.
Browser → /graph/api/v1/places/geocode?q=Berlin → Proxy (adds Authorization) → Qarta
The proxy is intentionally minimal — it only attaches the API key and forwards the request. It does not cache, transform, or restrict which endpoints can be called.
Download
Download api-proxy.zipThe zip contains proxy.py, pyproject.toml, and a full test suite.
Running the Proxy
Install dependencies:
unzip api-proxy.zip
cd api-proxy
pip install -e ".[dev]"
Start the server:
export QARTA_API_KEY=your_api_key_here
python proxy.py
# Listening on http://0.0.0.0:8081
Optional environment variables:
| Variable | Default | Description |
|---|---|---|
QARTA_API_KEY | (required) | Your Qarta API key |
QARTA_BASE_URL | https://graph.quarticle.ro | Upstream Qarta base URL |
PROXY_TIMEOUT | 30 | Upstream request timeout in seconds |
Making Requests Through the Proxy
Instead of calling Qarta directly with an API key in the browser:
// DON'T do this in the browser — exposes your API key
const response = await fetch(
'https://graph.quarticle.ro/graph/api/v1/places/geocode?q=Berlin',
{ headers: { 'Authorization': 'YOUR_API_KEY' } }
);
Call the proxy instead (no Authorization header needed in client-side code):
// DO this — the proxy adds the API key server-side
const response = await fetch('/graph/api/v1/places/geocode?q=Berlin');
const data = await response.json();
The proxy mirrors the full Qarta URL structure, so any path that works against https://graph.quarticle.ro works against the proxy by substituting the base URL.
POST requests with a JSON body work the same way:
const response = await fetch('/graph/api/v1/reports/portfolio/points/selection', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ points: [{ lat: 51.5, lon: -0.1 }] })
});
Proxy Source Code
import os
import requests
from flask import Flask, Response, request
QARTA_BASE_URL = os.getenv("QARTA_BASE_URL", "https://graph.quarticle.ro")
QARTA_API_KEY = os.getenv("QARTA_API_KEY")
PROXY_TIMEOUT = int(os.getenv("PROXY_TIMEOUT", "30"))
# Headers from client requests that must not be forwarded upstream
_STRIP_HEADERS = {"host", "authorization", "transfer-encoding", "connection", "content-length"}
app = Flask(__name__)
@app.route("/<path:path>", methods=["GET", "POST", "PUT", "DELETE", "PATCH"])
def proxy(path: str) -> Response:
upstream_url = f"{QARTA_BASE_URL}/{path}"
forward_headers = {"Authorization": QARTA_API_KEY}
for key, value in request.headers:
if key.lower() not in _STRIP_HEADERS:
forward_headers[key] = value
resp = requests.request(
method=request.method,
url=upstream_url,
params=request.args,
data=request.get_data(),
headers=forward_headers,
timeout=PROXY_TIMEOUT,
stream=True,
)
return Response(
resp.iter_content(chunk_size=8192),
status=resp.status_code,
content_type=resp.headers.get("Content-Type", "application/octet-stream"),
)
if __name__ == "__main__":
if not QARTA_API_KEY:
raise RuntimeError("QARTA_API_KEY environment variable is required")
app.run(host="0.0.0.0", port=8081)
Running the Tests
cd api-proxy
pytest tests/ -v
The tests use responses to mock all upstream Qarta calls — no real network requests are made.
Next Steps
- GeoServer Proxy — dedicated proxy for WMS/WFS endpoints used in browser maps
- Authentication Guide — full API key security guidance
- Quickstart Guide — explore available Qarta endpoints