Files
lead-scraper/app/api/credentials/test/route.ts
Timo Uttenweiler 7486517827 feat: add Google Maps → Email pipeline (Tab 4)
- New Maps page with keyword + region chips, German city presets, query preview, enrichment toggle
- Google Maps Places API (New) service with pagination and deduplication
- maps-enrich job route: Maps search → store raw leads → optional Anymailfinder bulk enrichment
- Settings: Google Maps API key credential card with Places API instructions
- Sidebar: MapPin nav item + googlemaps credential status indicator
- Results: maps job type with MapPin icon (text-green-400)
- Credentials API: added googlemaps to SERVICES array and test endpoint

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 11:40:08 +01:00

66 lines
2.4 KiB
TypeScript

import { NextRequest, NextResponse } from "next/server";
import { prisma } from "@/lib/db";
import { decrypt } from "@/lib/utils/encryption";
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 cred = await prisma.apiCredential.findUnique({ where: { service } });
if (!cred?.value) return NextResponse.json({ ok: false, error: "Not configured" });
const key = decrypt(cred.value);
if (!key) return NextResponse.json({ ok: false, error: "Empty key" });
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 });
}
}