- Neuer getApiKey() Helper: prüft zuerst ENV-Vars, dann DB - Alle Job-Routes nutzen getApiKey() statt direktem DB-Lookup - Credentials-Status berücksichtigt ENV-Vars (Sidebar-Haken) - .env.local.example: Platzhalter für alle 4 API Keys Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
62 lines
2.2 KiB
TypeScript
62 lines
2.2 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
import { getApiKey } from "@/lib/utils/apiKey";
|
|
import axios from "axios";
|
|
|
|
export async function GET(req: NextRequest) {
|
|
const service = req.nextUrl.searchParams.get("service");
|
|
if (!service) return NextResponse.json({ ok: false, error: "Missing service" }, { status: 400 });
|
|
|
|
const key = await getApiKey(service);
|
|
if (!key) return NextResponse.json({ ok: false, error: "Not configured" });
|
|
|
|
try {
|
|
switch (service) {
|
|
case "anymailfinder": {
|
|
// Test with a known domain — no credits charged if email not found
|
|
const res = await axios.post(
|
|
"https://api.anymailfinder.com/v5.1/find-email/decision-maker",
|
|
{ domain: "microsoft.com", decision_maker_category: ["ceo"] },
|
|
{ headers: { Authorization: key }, timeout: 15000 }
|
|
);
|
|
return NextResponse.json({ ok: res.status === 200 });
|
|
}
|
|
case "apify": {
|
|
const res = await axios.get("https://api.apify.com/v2/users/me", {
|
|
params: { token: key },
|
|
timeout: 10000,
|
|
});
|
|
return NextResponse.json({ ok: res.status === 200 });
|
|
}
|
|
case "vayne": {
|
|
const res = await axios.get("https://www.vayne.io/api/credits", {
|
|
headers: { Authorization: `Bearer ${key}` },
|
|
timeout: 10000,
|
|
});
|
|
return NextResponse.json({ ok: res.status === 200 });
|
|
}
|
|
case "googlemaps": {
|
|
const res = await axios.post(
|
|
"https://places.googleapis.com/v1/places:searchText",
|
|
{ textQuery: "restaurant", maxResultCount: 1 },
|
|
{
|
|
headers: {
|
|
"X-Goog-Api-Key": key,
|
|
"X-Goog-FieldMask": "places.id",
|
|
"Content-Type": "application/json",
|
|
},
|
|
timeout: 10000,
|
|
}
|
|
);
|
|
return NextResponse.json({ ok: res.status === 200 });
|
|
}
|
|
default:
|
|
return NextResponse.json({ ok: false, error: "Unknown service" });
|
|
}
|
|
} catch (err) {
|
|
const status = (err as { response?: { status?: number } })?.response?.status;
|
|
// 402 Payment Required = valid key but no credits → still connected
|
|
if (status === 402) return NextResponse.json({ ok: true });
|
|
return NextResponse.json({ ok: false });
|
|
}
|
|
}
|