Skip to Content
REST APIGetting Started

Getting Started

The zkStash REST API provides a powerful interface for interacting with the memory layer directly. This guide covers the essential concepts of authentication and payments required to use the API.

Base URL

All API requests should be made to:

https://api.zkstash.ai

Authentication

zkStash uses a wallet-based authentication mechanism. Every request must be signed by a valid EVM or Solana wallet.

Required Headers

Include the following headers in every request:

HeaderDescription
x-wallet-addressYour public wallet address (e.g., 0x... or SolanaAddress...).
x-wallet-signatureA cryptographic signature of the request details.
x-wallet-timestampThe current Unix timestamp (in milliseconds). Must be within 2 minutes of the server time.

Generating the Signature

To generate the x-wallet-signature, you must sign a canonical message constructed from the request details.

1. Construct the Canonical Message

The message format is:

METHOD|PATH|BODY_HASH|TIMESTAMP
  • METHOD: The HTTP method in uppercase (e.g., POST, GET, PATCH).
  • PATH: The request path (e.g., /memories). Do not include query parameters.
  • BODY_HASH: The SHA-256 hash of the request body (hex string).
    • If there is no body (e.g., GET requests), use the hash of an empty string.
  • TIMESTAMP: The exact timestamp value used in the x-wallet-timestamp header.

2. Sign the Message

Sign the canonical message string using your wallet’s private key.

  • EVM: Use signMessage().
  • Solana: Use signMessages().

Example (Node.js)

const crypto = require('crypto'); const ethers = require('ethers'); // For EVM const nacl = require('tweetnacl'); // For Solana const bs58 = require('bs58'); async function generateHeaders(method, path, body, privateKey, chain = 'evm') { const timestamp = Date.now().toString(); // 1. Hash the body const bodyString = body ? JSON.stringify(body) : ''; const bodyHash = crypto.createHash('sha256').update(bodyString).digest('hex'); // 2. Create Canonical Message const message = `${method.toUpperCase()}|${path}|${bodyHash}|${timestamp}`; let signature; let address; if (chain === 'evm') { const wallet = new ethers.Wallet(privateKey); address = wallet.address; signature = await wallet.signMessage(message); } else { // Solana implementation const keyPair = nacl.sign.keyPair.fromSecretKey(bs58.decode(privateKey)); address = bs58.encode(keyPair.publicKey); const messageBytes = new TextEncoder().encode(message); const signatureBytes = nacl.sign.detached(messageBytes, keyPair.secretKey); signature = Buffer.from(signatureBytes).toString('base64'); } return { 'x-wallet-address': address, 'x-wallet-timestamp': timestamp, 'x-wallet-signature': signature, 'Content-Type': 'application/json' }; }

Payment Flow (x402)

zkStash implements the x402 protocol for metered API usage. This allows for permissionless, pay-as-you-go access using crypto.

402 Payment Required

If your account (wallet) does not have enough free credits, the API will return a 402 Payment Required status. The response body will contain the payment requirements.

Example 402 Response:

{ "x402Version": 1, "error": "X-PAYMENT header is required", "accepts": [ { "network": "solana-devnet", "token": "USDC", "amount": "0.1", "recipient": "CKPKJWNdJEqa81x7CkZ14BVPiY6y16Sxs7owznqtWYp5" }, { "network": "base-sepolia", "token": "USDC", "amount": "0.1", "recipient": "0x..." } ] }

Handling Payments

  1. Check for 402: Inspect the response status code.
  2. Select Network: Choose a supported network from the accepts list (e.g., solana-devnet).
  3. Execute Transaction: Send the specified amount of token to the recipient address on-chain.
  4. Retry with Proof: Retry the original API request, adding the x-payment header.

The x-payment header should contain a base64-encoded JSON object with the transaction details (proof).

Supported Networks:

  • solana-devnet
  • base-sepolia

Response Codes

StatusMeaningDescription
200OKThe request was successful.
400Bad RequestInvalid parameters or body schema. Check the error message for details.
401UnauthorizedInvalid signature, timestamp expired (> 2 mins), or malformed headers.
402Payment RequiredInsufficient credits. Payment required to proceed.
404Not FoundThe requested resource (memory, schema) does not exist.
500Internal ErrorSomething went wrong on the server.
Last updated on