AeroModel
Documentation
API key safety — do not expose it
The API key generates images without watermark. If it leaks, anyone can consume your quota.
Bad practices (DO NOT DO)
❌ Hard-coded key in HTML
<!-- VISIBLE TO EVERYONE -->
<img src="https://api.aeromodel.dash-systems.fr/v1/images/plane?plane=A320&api-key=sk_live_abcd1234" />
❌ Key in JavaScript bundle
// COMPILED INTO THE PUBLIC BUNDLE, VISIBLE IN F12
const KEY = "sk_live_abcd1234";
fetch(`/v1/images/plane?plane=A320`, { headers: { "x-api-key": KEY } });
❌ Key in a client-exposed env variable
# Next.js — ALL NEXT_PUBLIC_* vars are exposed to the browser
NEXT_PUBLIC_AEROMODEL_KEY=sk_live_abcd1234 # ❌
# Vite — all VITE_* vars are exposed
VITE_AEROMODEL_KEY=sk_live_abcd1234 # ❌
❌ Key committed to git
Even in a private repo, consider the key compromised once it's in git. Rotate it immediately.
Good practices
✅ Pattern 1: display the image directly
If you only want to display an image on a public web page, don't use a key:
<img src="https://api.aeromodel.dash-systems.fr/v1/images/plane?plane=A320&airline=AF" />
The image is served with a watermark (transparent Aeromodel logo). This is the intended mode for free public use.
✅ Pattern 2: backend proxy
For unwatermarked client-side images, route through your own server:
[Browser] --GET /api/plane/A320--> [Your backend] --GET /v1/images/plane (with key)--> [Aeromodel API]
Express / Node.js
import express from "express";
const app = express();
const KEY = process.env.AEROMODEL_API_KEY; // server-side only
app.get("/api/plane/:slug", async (req, res) => {
const url = new URL("https://api.aeromodel.dash-systems.fr/v1/images/plane");
url.searchParams.set("plane", req.params.slug);
url.searchParams.set("airline", req.query.airline ?? "");
url.searchParams.set("resolution", "card");
url.searchParams.set("align", "bottom");
const upstream = await fetch(url, { headers: { "x-api-key": KEY } });
res.setHeader("content-type", upstream.headers.get("content-type"));
res.setHeader("cache-control", "public, max-age=86400");
upstream.body.pipe(res);
});
Cloudflare Worker (zero-config proxy)
export default {
async fetch(request, env) {
const url = new URL(request.url);
const upstream = new URL("https://api.aeromodel.dash-systems.fr/v1/images/plane");
for (const [k, v] of url.searchParams) upstream.searchParams.set(k, v);
return fetch(upstream, { headers: { "x-api-key": env.AEROMODEL_KEY } });
}
};
Next.js route handler
// app/api/plane/route.ts
export async function GET(req: Request) {
const incoming = new URL(req.url);
const upstream = new URL("https://api.aeromodel.dash-systems.fr/v1/images/plane");
for (const [k, v] of incoming.searchParams) upstream.searchParams.set(k, v);
const r = await fetch(upstream, { headers: { "x-api-key": process.env.AEROMODEL_KEY! } });
return new Response(r.body, {
status: r.status,
headers: {
"content-type": r.headers.get("content-type") ?? "image/png",
"cache-control": "public, max-age=86400"
}
});
}
✅ Pattern 3: signed URLs (roadmap)
Roadmap — /v1/sign endpoint generating short-lived signed image URLs. Lets you serve client URLs without revealing the key. Not yet available.
Storing the key in production
| Platform | Method |
|---|---|
| Cloudflare Workers | wrangler secret put AEROMODEL_API_KEY |
| Vercel / Netlify | Env vars (without NEXT_PUBLIC_ / VITE_) |
| AWS Lambda | AWS Secrets Manager or Lambda env vars |
| Docker | Docker secret, gitignored .env file |
| GitHub Actions | ${{ secrets.AEROMODEL_API_KEY }} |
| Local dev | .env.local (in .gitignore) |
What to do if a key leaks
- Contact the admin immediately to rotate (
wrangler secret put API_KEYSwith the new value). - Find the source of the leak (commit, screenshot, public log...).
- Check abnormal requests in Cloudflare Workers Analytics.
- Update your backend services with the new key.