> For the complete documentation index, see [llms.txt](https://docs.bv7x.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.bv7x.ai/use-the-signal/read-the-forecast/token-verification.md).

# Token Verification

Prove your $BV7X token holdings to unlock gated API endpoints. Verification uses EIP-191 signed messages -- no tokens are transferred or locked.

***

## How It Works

1. **Sign a message** with your wallet (MetaMask, ethers.js, web3.py, etc.)
2. **POST the signature** to the verify endpoint
3. **Receive a bearer token** valid for 30 minutes
4. **Include the token** in the `Authorization` header on subsequent requests

***

## Message Format

The message you sign must match this exact format:

```
Verify BV7X balance: <wallet_address>:<unix_timestamp>
```

* `wallet_address` -- your checksummed Ethereum address (Base network)
* `unix_timestamp` -- current Unix time in seconds (must be within 5 minutes of server time)

Example:

```
Verify BV7X balance: 0xd8B71d23e1a8da9867497C0E757A1143B94C3e1e:1711647600
```

***

## Verify Endpoint

```
POST /api/bv7x/oracle/verify
Content-Type: application/json
```

### Request Body

```json
{
  "wallet": "0xd8B71d23e1a8da9867497C0E757A1143B94C3e1e",
  "signature": "0x1a2b3c...",
  "timestamp": 1711647600
}
```

### Response

```json
{
  "success": true,
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "tier": "basic",
  "balance": "750000000",
  "expiresAt": "2026-03-28T22:30:00Z"
}
```

| Field       | Description                                         |
| ----------- | --------------------------------------------------- |
| `token`     | JWT bearer token for authenticated requests         |
| `tier`      | `basic` (500M+) or `premium` (1B+) based on balance |
| `balance`   | Your $BV7X balance (raw token units)                |
| `expiresAt` | Token expiry (30 minutes from issue)                |

### Error Responses

| Status | Reason                                       |
| ------ | -------------------------------------------- |
| 400    | Missing fields or timestamp out of range     |
| 403    | Signature valid but balance below 500M $BV7X |
| 401    | Invalid signature or address mismatch        |

***

## Using the Bearer Token

Include the token in the `Authorization` header:

```bash
curl https://bv7x.ai/api/bv7x/oracle \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
```

When the token expires, sign a new message and verify again.

***

## Python Example

```python
from web3 import Web3
from eth_account.messages import encode_defunct
import requests, time

wallet = "0xYourWalletAddress"
private_key = "0xYourPrivateKey"
timestamp = int(time.time())

message = f"Verify BV7X balance: {wallet}:{timestamp}"
signed = Web3().eth.account.sign_message(
    encode_defunct(text=message), private_key=private_key
)

resp = requests.post("https://bv7x.ai/api/bv7x/oracle/verify", json={
    "wallet": wallet,
    "signature": signed.signature.hex(),
    "timestamp": timestamp,
})
token = resp.json()["token"]

signal = requests.get("https://bv7x.ai/api/bv7x/oracle",
    headers={"Authorization": f"Bearer {token}"}
).json()
print(signal)
```

***

## Node.js Example

```javascript
import { ethers } from "ethers";

const wallet = new ethers.Wallet("0xYourPrivateKey");
const timestamp = Math.floor(Date.now() / 1000);
const message = `Verify BV7X balance: ${wallet.address}:${timestamp}`;
const signature = await wallet.signMessage(message);

const verifyRes = await fetch("https://bv7x.ai/api/bv7x/oracle/verify", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ wallet: wallet.address, signature, timestamp }),
});
const { token } = await verifyRes.json();

const signal = await fetch("https://bv7x.ai/api/bv7x/oracle", {
  headers: { Authorization: `Bearer ${token}` },
}).then((r) => r.json());
console.log(signal);
```

***

## Next

* [Oracle API](/use-the-signal/read-the-forecast/oracle.md) -- full signal with direction and confidence
* [Token Gate Tiers](/agentic-commerce/token-gate.md) -- what each tier unlocks
