Skip to main content
Sign-In with X (SIWX) lets you authenticate with ChainStream by signing a message with your wallet on every API request — no API Key or OAuth token needed. This is designed for AI agents with on-chain wallets that have purchased a subscription via x402 payment.
SIWX replaces the API Key. Instead of passing X-API-KEY, you pass Authorization: SIWX <token> on each request. The gateway verifies the signature and checks for a valid x402 subscription in real time.

How It Works

Unlike traditional challenge/response flows, SIWX is stateless and self-contained. The client constructs and signs the message locally, then attaches it to every request.

Step-by-Step

  1. Construct an EIP-4361 message with your wallet address, domain, nonce, and expiration time
  2. Sign the message with your wallet private key
  3. Encode as SIWX token: base64(message).signature
  4. Attach to every API request: Authorization: SIWX <token>
  5. The gateway verifies the signature and checks that the wallet has an active x402 subscription
  6. If valid, the request proceeds normally (same as API Key auth)

Token Format

Authorization: SIWX base64(message).signature
The message follows the EIP-4361 standard:
api.chainstream.io wants you to sign in with your Ethereum account:
0xYourWalletAddress

Sign in to ChainStream API

URI: https://api.chainstream.io
Version: 1
Chain ID: 8453
Nonce: abc123def456
Issued At: 2026-03-26T10:00:00Z
Expiration Time: 2026-03-27T10:00:00Z

Required Fields

FieldDescription
DomainMust be api.chainstream.io
AddressYour wallet address (EVM 0x... or Solana base58)
URIhttps://api.chainstream.io
Version1
NonceA random string (client-generated, for replay protection)
Issued AtISO 8601 timestamp
Expiration TimeISO 8601 timestamp (the token is rejected after this time)
The expiration time is set by the client. You can sign a message valid for minutes, hours, or days. A longer expiration means fewer re-signs, but a shorter one is more secure.

Supported Chains

ChainAddress FormatSignature Verification
EVM (Base, Ethereum)0x prefixed, 40 hex charsEIP-191 personal_sign recovery
SolanaBase58 encoded, 32-44 charsEd25519 signature verification

Prerequisites

SIWX authentication requires an active x402 subscription linked to the wallet address. Without a subscription, the gateway rejects the request with an error. To get a subscription:
# Via CLI (automatic)
chainstream login
chainstream token info --chain sol --address So11111111111111111111111111111111111111112
# → 402 triggers plan selection → x402 payment → API Key saved

# Or via direct x402 purchase
curl https://api.chainstream.io/x402/purchase?plan=nano
# → Follow x402 payment flow
See x402 Payment for details.

Usage Examples

cURL

# 1. Construct and sign the message (using your preferred tool)
# 2. Base64-encode the message and append the signature
TOKEN="base64EncodedMessage.signatureHex"

# 3. Use on any API call
curl https://api.chainstream.io/v2/token/sol/So11111111111111111111111111111111111111112 \
  -H "Authorization: SIWX $TOKEN"

SDK

import { ChainStreamClient } from "@chainstream-io/sdk";

const cs = new ChainStreamClient({
  auth: {
    type: "siwx",
    address: "0xYourWalletAddress",
    signMessage: async (message: string) => {
      return await wallet.signMessage(message);
    },
  },
});

const token = await cs.token.getToken("So11111111111111111111111111111111111111112", "sol");

CLI

The CLI uses SIWX automatically when you log in with a wallet:
chainstream login
chainstream token info --chain sol --address So11111111111111111111111111111111111111112

SIWX vs API Key

SIWXAPI Key
HeaderAuthorization: SIWX <token>X-API-KEY: <key>
Credential managementNo key to store — sign on demandStore and protect the key
PrerequisiteWallet + x402 subscriptionDashboard account
Best forAI agents with walletsApplications, scripts, MCP
Token expirySet by client (per-message)Set in Dashboard (or never)

Security Considerations

  • Stateless: No server-side session. Each request is independently verified.
  • Expiration: The client controls token lifetime via the Expiration Time field. Expired tokens are rejected.
  • Domain binding: The message includes api.chainstream.io as the domain. Signatures for other domains are rejected.
  • No private key exposure: The wallet only signs a plaintext message — the private key is never transmitted.
  • Subscription check: Even with a valid signature, the request is rejected if the wallet has no active x402 subscription.