> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tallyscrape.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Credits & billing

> How the prepaid credit model works, and how to top up.

## Prepaid model

Tallyscrape is **prepaid**: you buy credits up front, and each successful scrape debits
your balance. There is no subscription and no monthly minimum.

Key rules:

* **You are billed only on a real success** — `success: true` **and** `blocked: false`.
  Failed requests, timeouts, and anti-bot pages cost nothing.
* **The cost is the tier actually used.** If you request a proxy but the pool falls back
  to a direct connection, you are billed at the `none` rate (see `proxy_used` on
  [`POST /scrape`](/endpoints/scrape)).
* **The balance never goes negative.** If your balance is too low for the requested cost,
  the request is rejected up front with **402** — nothing is scraped.

See the full rate grid on [Pricing](/pricing).

## Buying credits

Credits are purchased through Stripe Checkout. Call `POST /credits/buy` to get a payment
URL, then redirect the user to it. Your balance is credited automatically once the
payment completes.

```
POST https://api.tallyscrape.com/credits/buy
```

Provide **either** a predefined `pack` **or** a free `amount_eur` (not both):

<ParamField body="pack" type="string">
  A predefined pack in euros: `"10"`, `"50"`, or `"100"`.
</ParamField>

<ParamField body="amount_eur" type="number">
  A custom amount in euros. Minimum **5 €**.
</ParamField>

The conversion rate is fixed: **1 € = 1000 credits**.

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://api.tallyscrape.com/credits/buy \
    -H "X-API-Key: spy_your_api_key" \
    -H "Content-Type: application/json" \
    -d '{ "pack": "50" }'
  ```

  ```python Python theme={null}
  import requests

  resp = requests.post(
      "https://api.tallyscrape.com/credits/buy",
      headers={"X-API-Key": "spy_your_api_key"},
      json={"pack": "50"},          # or {"amount_eur": 25}
  )
  checkout_url = resp.json()["url"]
  print("Pay here:", checkout_url)
  ```

  ```javascript JavaScript theme={null}
  const resp = await fetch("https://api.tallyscrape.com/credits/buy", {
    method: "POST",
    headers: {
      "X-API-Key": "spy_your_api_key",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ pack: "50" }), // or { amount_eur: 25 }
  });
  const { url } = await resp.json();
  console.log("Pay here:", url);
  ```

  ```java Java theme={null}
  import java.net.URI;
  import java.net.http.*;

  var body = "{\"pack\":\"50\"}"; // or {"amount_eur":25}

  var request = HttpRequest.newBuilder()
      .uri(URI.create("https://api.tallyscrape.com/credits/buy"))
      .header("X-API-Key", "spy_your_api_key")
      .header("Content-Type", "application/json")
      .POST(HttpRequest.BodyPublishers.ofString(body))
      .build();

  var response = HttpClient.newHttpClient()
      .send(request, HttpResponse.BodyHandlers.ofString());
  System.out.println(response.body());
  ```
</CodeGroup>

### Response

```json theme={null}
{ "url": "https://checkout.stripe.com/c/pay/cs_test_..." }
```

Redirect the user to this URL to complete payment. Credits are added to the balance only
after Stripe confirms the payment.

<Note>
  Running low mid-request? A scrape whose cost exceeds your balance returns **402 Payment
  Required** without scraping. Top up, then retry. See [Errors](/errors).
</Note>
