# Handle 402s and top-ups gracefully

> VendorStacks — the subprocessor disclosure data API. Canonical: https://vendorstacks.com
/docs/guides/handle-402s/


The paywall anatomy, why nothing is ever half-charged, and the retry-after-payment pattern for scripts and agents.

Every VendorStacks request is priced before it runs. If the key's balance can't cover it, the API returns `402 payment_required` and charges nothing — there is no partial state to clean up, which makes the retry logic trivial.

### Anatomy

```
HTTP/1.1 402 Payment Required
X-Request-Id: 9f6f4a1e-…

{
  "error": "payment_required",
  "message": "This request costs 1 credit; balance is 0.",
  "remaining_credits": 3,
  "credits_needed": 10,
  "topup_url": "https://vendorstacks.com/app/billing"
}
```

- `credits_needed` is the price of *this* request, not a suggested pack size.
- `topup_url` goes straight to billing — pass it to whoever holds the card.
- The failed request is safe to retry byte-for-byte after top-up.

### Script pattern: pause, poll, resume

**retry-after-payment**

```
async function callWithTopupPause(url, opts, key) {
  for (;;) {
    const res = await fetch(url, opts);
    if (res.status !== 402) return res;

    const { topup_url, credits_needed } = await res.json();
    console.error(`Paused: need ${credits_needed} credits → ${topup_url}`);

    // Poll the free balance endpoint until a top-up lands, then resume.
    for (;;) {
      await new Promise(r => setTimeout(r, 30_000));
      const bal = await fetch("https://vendorradar-production.up.railway.app
/v1/balance", {
        headers: { Authorization: `Bearer ${key}` },
      }).then(r => r.json());
      if (bal.credit_balance >= credits_needed) break;
    }
  }
}
```

`/v1/balance` is free to call, so the poll loop costs nothing. For agents, don't poll — relay `topup_url` to the human and end the turn; see [the agent guide](/docs/guides/agent-tool). For batch jobs, checking [/v1/pricing](/docs/api#pricing) and `/v1/balance` up front lets you fail before doing half the work.