> ## Documentation Index
> Fetch the complete documentation index at: https://ti-mm-mycompc.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Claim a Solana API Key with Wallet Authentication

> Top up your Solana wallet, sign a challenge with your keypair, and claim a credit-metered API key for the Solana Pulse AI Agent Gateway.

Solana Pulse AI Agent Gateway issues credit-metered API keys through wallet-based authentication. You top up by sending SOL to the gateway wallet, then sign a challenge with your Solana keypair to prove ownership and claim your key. This guide walks through the entire flow from funding to a working API key.

<Steps>
  <Step title="Top up your wallet">
    Send SOL to the gateway wallet address to create a pending API key balance:

    ```text theme={null}
    Brpc8HoPo1d3Uiyo7kbERnjMqwLJJmbWxtwxHxzar6DU
    ```

    The gateway listens for your transfer via a Helius webhook. Once confirmed, a pending claim is created for your wallet address. You do not need to wait for a notification; the claim endpoint will tell you when your key is ready.
  </Step>

  <Step title="Fetch a challenge">
    Request a random 32-byte challenge from the gateway. You will sign this value to prove ownership of your wallet.

    ```bash theme={null}
    curl https://solana-pulse-ai-agent-gateway.ai.studio/api/keys/challenge
    ```

    Expected response:

    ```json theme={null}
    {
      "challenge": "a1b2c3d4e5f6..."
    }
    ```
  </Step>

  <Step title="Sign the challenge">
    Use `@solana/web3.js` and `tweetnacl` to sign the challenge with your keypair. The signature must be base58-encoded.

    ```typescript theme={null}
    import { Keypair } from "@solana/web3.js";
    import nacl from "tweetnacl";
    import bs58 from "bs58";

    // Load your wallet keypair (replace with your own secret key)
    const secretKey = Uint8Array.from([/* 64-byte secret key */]);
    const keypair = Keypair.fromSecretKey(secretKey);
    const wallet = keypair.publicKey.toBase58();

    // Fetch challenge from gateway
    const challengeRes = await fetch("https://solana-pulse-ai-agent-gateway.ai.studio/api/keys/challenge");
    const { challenge } = await challengeRes.json();

    // Sign challenge
    const message = Buffer.from(challenge, "hex");
    const signature = nacl.sign.detached(message, keypair.secretKey);
    const signatureBase58 = bs58.encode(signature);

    console.log("Wallet:", wallet);
    console.log("Signature:", signatureBase58);
    ```
  </Step>

  <Step title="Claim your API key">
    POST the wallet address, base58 signature, and challenge back to the gateway.

    ```typescript theme={null}
    const claimRes = await fetch("https://solana-pulse-ai-agent-gateway.ai.studio/api/keys/claim", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        wallet,
        signature: signatureBase58,
        challenge
      })
    });

    const claimData = await claimRes.json();
    console.log("API Key:", claimData.apiKey);
    ```

    Success response:

    ```json theme={null}
    {
      "apiKey": "3f2a1b4c...",
      "message": "Your secure API key has been claimed. Keep it secret!"
    }
    ```

    <Warning>
      Store your API key securely. It is shown only once at claim time and cannot be retrieved again.
    </Warning>
  </Step>

  <Step title="Use your key on paid endpoints">
    Pass the key in the `x-api-key` header on every paid request:

    ```bash theme={null}
    curl -H "x-api-key: 3f2a1b4c..." \
      "https://solana-pulse-ai-agent-gateway.ai.studio/api/solana/token-accounts?wallet=YOUR_WALLET&network=mainnet-beta"
    ```
  </Step>
</Steps>

## Full end-to-end script

Here is a complete TypeScript script you can run with `tsx` or `ts-node`:

```typescript theme={null}
import { Keypair } from "@solana/web3.js";
import nacl from "tweetnacl";
import bs58 from "bs58";

const GATEWAY = "https://solana-pulse-ai-agent-gateway.ai.studio";

async function claimApiKey(secretKeyUint8: Uint8Array) {
  const keypair = Keypair.fromSecretKey(secretKeyUint8);
  const wallet = keypair.publicKey.toBase58();

  // 1. Fetch challenge
  const challengeRes = await fetch(`${GATEWAY}/api/keys/challenge`);
  const { challenge } = await challengeRes.json();

  // 2. Sign challenge
  const message = Buffer.from(challenge, "hex");
  const signature = nacl.sign.detached(message, keypair.secretKey);
  const signatureBase58 = bs58.encode(signature);

  // 3. Claim key
  const claimRes = await fetch(`${GATEWAY}/api/keys/claim`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ wallet, signature: signatureBase58, challenge })
  });

  if (!claimRes.ok) {
    const err = await claimRes.json();
    throw new Error(err.error || "Claim failed");
  }

  const { apiKey, message: msg } = await claimRes.json();
  console.log("Claimed!", msg);
  return apiKey;
}

// Replace with your actual secret key array
const MY_SECRET_KEY = Uint8Array.from([/* 64 bytes */]);
claimApiKey(MY_SECRET_KEY)
  .then(key => console.log("Store this key:", key))
  .catch(console.error);
```

## Error handling

| Status | Meaning                                 | What to do                                                         |
| ------ | --------------------------------------- | ------------------------------------------------------------------ |
| 400    | Missing wallet, signature, or challenge | Check your request body                                            |
| 401    | Invalid signature                       | Verify you signed the exact challenge hex with the correct keypair |
| 404    | No pending key found                    | Send SOL to the gateway wallet and wait for confirmation           |
| 500    | Server error                            | Retry after a moment                                               |

## Result

You now have a credit-metered API key tied to your Solana wallet. Every paid call debits your balance by 0.0022 SOL (2,200,000 lamports). You also receive 50 lifetime free calls and 15 free calls per day before credits are consumed.

## Next steps

* [Decode a transaction](/guides/decode-transaction) to turn raw signatures into LLM-friendly summaries
* [MCP Integration](/guides/mcp-integration) to connect the gateway to Claude Desktop or Cursor
