---
name: bazaarlink-probe
description: Verify the identity and quality of any OpenAI-compatible API endpoint — detect model swap, token inflation, system prompt injection (model leak), and dependency hijacking on relay stations / proxies / upstream providers. Runs 50+ automated probes via the BazaarLink Probe API and returns a 0–100 score plus V3 sub-model identity verdict. Use when the user wants to verify whether a relay / proxy / upstream is actually serving the claimed model, audit upstream provider quality, or detect API manipulation.
---

# BazaarLink Probe — Upstream Detection Skill

Run multi-layer identity verification and quality probing against any OpenAI-compatible endpoint (`baseUrl + apiKey + modelId`).

**Why this matters**: relay-station / reverse-proxy operators can use this API to **continuously verify their own upstream providers** — confirming nobody is silently swapping the model out or inflating tokens.

---

## Most common: fast identity check

```bash
curl -X POST https://bazaarlink.ai/api/probe/run \
  -H "Content-Type: application/json" \
  -d '{
    "baseUrl": "https://your-upstream.com/v1",
    "apiKey": "sk-...",
    "modelId": "anthropic/claude-opus-4.7",
    "quickMode": true,
    "identityOnly": true,
    "sync": true
  }'
```

**Response (30–60 s)**:

```json
{
  "runId": "uuid",
  "status": "completed",
  "score": 87,
  "identityAssessment": {
    "status": "confirmed",
    "confidence": 0.92,
    "claimedModel": "anthropic/claude-opus-4.7",
    "predictedFamily": "claude",
    "predictedCandidates": [...],
    "subModelMatchV3F": {
      "modelId": "anthropic/claude-opus-4.7",
      "score": 0.94
    },
    "riskFlags": []
  },
  "items": [
    { "probeId": "submodel_cutoff", "passed": true, "response": "..." }
  ],
  "totalInputTokens": 3120,
  "totalOutputTokens": 2540
}
```

Key fields:
- `score` — 0–100 composite score
- `identityAssessment.status` — `confirmed` / `mismatch` / `insufficient_data`
- `subModelMatchV3F.modelId` — V3F classifier verdict at sub-model granularity (highest confidence)
- `riskFlags[]` — triggered risk flags (spoof / family mismatch / etc.)

---

## Three modes

| Mode | Params | Duration | Use case |
|---|---|---|---|
| **Fast identity** | `quickMode:true, identityOnly:true` | 20–40 s | Routine relay verification |
| **Full** | (both false) | 60–180 s | First-time vendor onboarding |
| **+ Context test** | `runContextCheck:true` | 3–5 min | Deep quality audit |

---

## Request parameters

| Param | Type | Required | Description |
|---|---|---|---|
| `baseUrl` | string | ✅ | OpenAI-compatible base URL |
| `apiKey` | string | ✅ | Key for the target endpoint (used only for this run, never stored) |
| `modelId` | string | ✅ | Model ID on the endpoint |
| `claimedModel` | string | ⚪ | Model the upstream claims to serve (used for spoof comparison when different from `modelId`) |
| `upstreamFormat` | `"openai"` \| `"anthropic"` | ⚪ | Default `openai` |
| `quickMode` | boolean | ⚪ | Skip 10× family-verdict repetition, saves tokens |
| `identityOnly` | boolean | ⚪ | Run only identity group, skip multimodal / linguistic |
| `sync` | boolean | ⚪ | `true` = wait and return full result; `false` = return runId immediately, poll yourself |
| `runContextCheck` | boolean | ⚪ | Additional 4K→128K context test |
| `lang` | string | ⚪ | Response language (`en` / `zh` / `ja` / etc.) |

**Safety**: SSRF protection — private IPs (10.x, 192.168.x, localhost) are rejected; per-IP rate limit applies.

---

## Mode B: async polling

For environments with short timeouts (e.g. Vercel Edge):

```bash
# 1. start
RUN=$(curl -sX POST https://bazaarlink.ai/api/probe/run \
  -H "Content-Type: application/json" \
  -d '{"baseUrl":"...","apiKey":"...","modelId":"...","quickMode":true,"identityOnly":true}' \
  | jq -r .runId)

# 2. poll every 2s
while true; do
  R=$(curl -s https://bazaarlink.ai/api/probe/run/$RUN)
  S=$(echo "$R" | jq -r .status)
  [ "$S" = "completed" ] && echo "$R" | jq . && break
  [ "$S" = "failed" ] && echo "$R" && exit 1
  sleep 2
done
```

---

## Mode C: query a completed run

Results are persisted; query any time:

```bash
# full record
curl https://bazaarlink.ai/api/probe/history/<runId>

# last 100 runs
curl https://bazaarlink.ai/api/probe/history
```

---

## Python: batch upstream check

```python
import httpx

UPSTREAMS = [
    {"name": "vendor-A", "baseUrl": "https://a.example/v1", "apiKey": "sk-a..."},
    {"name": "vendor-B", "baseUrl": "https://b.example/v1", "apiKey": "sk-b..."},
]
MODEL = "anthropic/claude-opus-4.7"

def quick_probe(base_url, api_key, model_id):
    r = httpx.post(
        "https://bazaarlink.ai/api/probe/run",
        json={
            "baseUrl": base_url, "apiKey": api_key, "modelId": model_id,
            "quickMode": True, "identityOnly": True, "sync": True,
        },
        timeout=120,
    )
    r.raise_for_status()
    return r.json()

for up in UPSTREAMS:
    res = quick_probe(up["baseUrl"], up["apiKey"], MODEL)
    ident = res.get("identityAssessment", {})
    v3f = (ident.get("subModelMatchV3F") or {}).get("modelId")
    flags = ident.get("riskFlags", [])
    ok = ident.get("status") == "confirmed" and not flags
    print(f"{'OK ' if ok else 'BAD'} {up['name']}: score={res['score']} v3f={v3f} flags={flags}")
```

---

## TypeScript

```typescript
interface ProbeResponse {
  runId: string;
  status: "completed" | "running" | "failed";
  score: number;
  identityAssessment?: {
    status: "confirmed" | "mismatch" | "insufficient_data";
    confidence: number;
    claimedModel?: string;
    predictedFamily?: string;
    subModelMatchV3F?: { modelId: string; score: number } | null;
    riskFlags: string[];
  };
  items: Array<{
    probeId: string;
    label: string;
    group: "identity" | "submodel" | "quality" | "security" | "integrity";
    passed: boolean | "warning" | null;
    response?: string;
    ttftMs?: number;
    tps?: number;
  }>;
  totalInputTokens: number | null;
  totalOutputTokens: number | null;
}

async function quickProbe(baseUrl: string, apiKey: string, modelId: string): Promise<ProbeResponse> {
  const res = await fetch("https://bazaarlink.ai/api/probe/run", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      baseUrl, apiKey, modelId,
      quickMode: true, identityOnly: true, sync: true,
    }),
    signal: AbortSignal.timeout(120_000),
  });
  if (!res.ok) throw new Error(`Probe failed: ${res.status}`);
  return res.json();
}
```

---

## Relay-station operator workflow

**Scenario**: you operate an OpenAI-compatible relay and resell 5 upstream vendors. You want to confirm daily that none of them silently swap to a cheaper model.

```bash
for vendor in vendor-a vendor-b vendor-c; do
  curl -sX POST https://bazaarlink.ai/api/probe/run \
    -H "Content-Type: application/json" \
    -d "{
      \"baseUrl\": \"https://$vendor.example/v1\",
      \"apiKey\": \"$VENDOR_KEY\",
      \"modelId\": \"anthropic/claude-opus-4.7\",
      \"quickMode\": true,
      \"identityOnly\": true,
      \"sync\": true
    }" \
  | jq '{vendor: "'$vendor'", score, ident: .identityAssessment.subModelMatchV3F.modelId, flags: .identityAssessment.riskFlags}'
done
```

If `subModelMatchV3F.modelId` flips from `claude-opus-4.7` to `claude-haiku-4.5` one day → upstream is swapping models. Page someone.

---

## Public baseline API

Download official baseline responses for offline / self-hosted comparison:

```bash
# list models that have a baseline
curl https://bazaarlink.ai/api/probe/baselines

# fetch baseline for a specific model
curl https://bazaarlink.ai/api/probe/baselines?modelId=openai/gpt-4o
```

No auth required. `responseText` is truncated to 2000 chars.

---

## `items[]` groups

| group | content | example probeId |
|---|---|---|
| `identity` | model identity probes (V3 classifier inputs) | `submodel_cutoff`, `submodel_capability`, `submodel_refusal` |
| `submodel` | sub-model fine discrimination | linguistic / fingerprint family |
| `quality` | quality assessment | `zh_reasoning`, `code_gen`, `instruction_follow` |
| `security` | security / leakage | `infra_probe`, `bedrock_probe`, `identity_leak` |
| `integrity` | integrity | `token_inflation`, `sse_compliance`, `symbol_exact` |

---

## Notes

- **API key is not stored** — used only during this run to call the endpoint you specified
- **Results persist forever** — runId can always be retrieved via `/api/probe/history/<id>`
- **Per-IP rate limit** — roughly 5 runs per minute; contact BazaarLink for higher quota
- **Cloudflare Turnstile** — direct API calls usually unaffected; if blocked, pass `cfTurnstileToken`
- **Cost** — tokens are charged to your own API key on the target endpoint; BazaarLink does not bill separately

---

## Advanced: LLM judge

Configure `probe_judge_*` admin settings to enable a second model that compares responses to baseline using semantic similarity, improving pass/fail accuracy. Not needed for normal usage.

---

## Endpoint cheat sheet

| Endpoint | Method | Purpose |
|---|---|---|
| `/api/probe/run` | POST | Start a probe run |
| `/api/probe/run/[runId]` | GET | Poll status / result |
| `/api/probe/run/[runId]/stop` | POST | Stop a run (same IP) |
| `/api/probe/run/[runId]/retest` | POST | Re-run a single probe |
| `/api/probe/history` | GET | List recent runs |
| `/api/probe/history/[id]` | GET | Full record for a run |
| `/api/probe/baselines` | GET | Public baseline download |
| `/api/probe/models` | GET | Suggested model list |
| `/api/probe/fraud-list` | GET | Known-fraud endpoints |

---

Live tool: <https://bazaarlink.ai/probe>
This skill file: <https://bazaarlink.ai/probe-api-skill.md>
