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

# Authentication

> Authenticate with an API key or per-request x402 micropayments.

# Authentication

X1-BaaS supports **two authentication paths**. Pick one — you never need both on the
same request:

| Path        | Header                                | Best for                                                      | Billing                    |
| ----------- | ------------------------------------- | ------------------------------------------------------------- | -------------------------- |
| **API Key** | `Authorization: Bearer baas_live_...` | Subscription users, CI pipelines, agents with long-lived keys | Monthly subscription       |
| **x402**    | `X-PAYMENT: <base64 permit>`          | One-off requests, agents paying from a hot wallet             | Per-request (\$0.005 USDC) |

If a request has neither a valid API key nor a valid x402 permit, the API returns
`401 Unauthorized`.

## API keys

API keys are prefixed with `baas_live_` followed by 64 hex characters. The full key
is **only shown once** when you create it — store it securely.

```
baas_live_abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890
```

Send the key in the `Authorization` header on every authenticated request:

<CodeGroup>
  ```bash theme={null}
  curl https://api.tazpal.com/v1/crawl \
    -H "Authorization: Bearer baas_live_YOUR_KEY"
  ```

  ```python theme={null}
  import httpx

  headers = {"Authorization": "Bearer baas_live_YOUR_KEY"}
  resp = httpx.get("https://api.tazpal.com/v1/crawl", headers=headers)
  ```

  ```javascript Node.js theme={null}
  const headers = { Authorization: "Bearer baas_live_YOUR_KEY" };
  const resp = await fetch("https://api.tazpal.com/v1/crawl", { headers });
  ```
</CodeGroup>

<Warning>
  Never commit API keys to source control or expose them in client-side code. Use
  environment variables or a secret manager.
</Warning>

### Scopes

Keys are created with a comma-separated scope list. The default scope is
`scrape:read`. A key with `*` bypasses scope checks.

```
scrape:read
```

## x402 payments

x402 lets agents pay per request with **USDC on Base** — no account, no key, no
signup. Each successful scrape settles **\$0.005 USDC**.

<Info>
  **New to x402?** See the [x402 Wallet Setup](/x402-wallet-setup) guide for step-by-step instructions on setting up a wallet for your agent.
</Info>

The flow has three steps:

<Steps>
  <Step title="Fetch payment requirements">
    Call the public `GET /v1/pricing` endpoint to learn the recipient wallet, amount,
    network, and USDC contract.
  </Step>

  <Step title="Create a signed permit">
    Generate an **EIP-3009** transfer-with-authorization (signed permit) on Base for
    `$0.005 USDC`, payable to the recipient wallet.
  </Step>

  <Step title="Send it in the X-PAYMENT header">
    Base64-encode the permit JSON and attach it as `X-PAYMENT`.
  </Step>
</Steps>

```bash theme={null}
# 1. Fetch payment requirements
curl https://api.tazpal.com/v1/pricing
```

```json Response theme={null}
{
  "x402_enabled": true,
  "price_usd": "0.005",
  "token_address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
  "network": "base",
  "pay_to": "0x6520...8dA",
  "facilitator": "https://x402.org/facilitator",
  "payment_header": "X-PAYMENT"
}
```

```bash theme={null}
# 3. Scrape with the base64-encoded signed permit
curl -X POST https://api.tazpal.com/v1/scrape \
  -H "X-PAYMENT: eyJwYXlsb2FkIjp7Im5vbmNlIjoi..." \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com"}'
```

### Payment guarantees

<Tip>
  **You're only charged on success.** Payment is verified *before* the scrape and
  settled *only after* a successful result. Timeouts and connection failures return
  `payment_charged: false` and never settle.
</Tip>

* **Nonce replay protection** — each permit's nonce is cached (300s TTL) to prevent
  double-spend.
* **Failed scrapes are free** — the `payment_charged: false` flag is included in
  error responses.
* **Settlement result** — successful x402 scrapes return a `payment` object with the
  transaction hash.

<AccordionGroup>
  <Accordion title="What does a payment response look like?">
    ```json theme={null}
    "payment": {
      "settled": true,
      "amount_usd": "0.005",
      "transaction": "0x...",
      "network": "base",
      "payer": "0x...",
      "error": null
    }
    ```
  </Accordion>

  <Accordion title="Can I use both API key and x402 on one request?">
    Yes, but it's unnecessary. The API checks the API key first; if it's valid, the
    request proceeds as a subscription request. If no valid key is present, it falls
    back to verifying `X-PAYMENT`.
  </Accordion>
</AccordionGroup>

## Public endpoints (no auth)

These endpoints require no authentication:

| Endpoint               | Purpose                                       |
| ---------------------- | --------------------------------------------- |
| `GET /health`          | Liveness and browser-engine status            |
| `GET /v1/pricing`      | Current pricing and x402 payment requirements |
| `GET /v1/proxy/status` | Proxy pool status                             |
