Skip to content

Inference API

The inference API enables pay-per-use AI inference via the x402 protocol.


Endpoint

POST /api/inference/{modelId}

Request Flow

Step 1: Initial Request (No Payment)

POST /api/inference/1
Content-Type: application/json

{
  "input": "Bitcoin price surges to new all-time high amid ETF approval"
}

Step 2: Receive Payment Requirements (HTTP 402)

{
  "x402Version": 1,
  "accepts": [
    {
      "scheme": "exact",
      "network": "avalanche-fuji",
      "maxAmountRequired": "10000",
      "resource": "https://wasiai.io/api/inference/1",
      "description": "AI inference on Crypto Sentiment Analyzer",
      "payTo": "0x1234567890abcdef1234567890abcdef12345678",
      "asset": "0x5425890298aed601595a70AB815c96711a31Bc65",
      "maxTimeoutSeconds": 60
    }
  ],
  "error": "X-PAYMENT header is required",
  "_info": {
    "model": "Crypto Sentiment Analyzer",
    "agentId": 1,
    "priceFormatted": "$0.0100",
    "currency": "USDC"
  }
}

Step 3: Retry with Payment

POST /api/inference/1
Content-Type: application/json
X-PAYMENT: eyJ4NDAyVmVyc2lvbiI6MSwic2NoZW1lIjoiZXhhY3QiLCJuZXR3b3JrIjoiYXZhbGFuY2hlLWZ1amkiLCJwYXlsb2FkIjp7InNpZ25hdHVyZSI6IjB4Li4uIiwiYXV0aG9yaXphdGlvbiI6ey4uLn19fQ==

{
  "input": "Bitcoin price surges to new all-time high amid ETF approval",
  "agentId": 1
}

Step 4: Receive Result (HTTP 200)

{
  "ok": true,
  "result": {
    "task": "sentiment-analysis",
    "input_text": "Bitcoin price surges to new all-time high amid ETF approval",
    "sentiment": "positive",
    "confidence": 0.9234,
    "all_scores": [
      { "label": "positive", "score": 0.9234 },
      { "label": "neutral", "score": 0.0612 },
      { "label": "negative", "score": 0.0154 }
    ],
    "model": "ProsusAI/finbert",
    "model_name": "Crypto Sentiment Analyzer",
    "agent": "agent-1",
    "timestamp": "2024-12-11T12:00:00.000Z"
  },
  "latencyMs": 1250,
  "payment": {
    "txHash": "0xabc123def456789...",
    "payer": "0xUserWallet...",
    "amount": "10000",
    "amountFormatted": "$0.0100",
    "currency": "USDC",
    "verified": true
  },
  "agent": {
    "id": 1,
    "name": "Crypto Sentiment Analyzer"
  }
}

Request Parameters

Path Parameters

Parameter Type Required Description
modelId number Yes The model ID to run inference on

Headers

Header Required Description
Content-Type Yes Must be application/json
X-PAYMENT Conditional Base64-encoded payment payload (required after 402)

Body Parameters

Parameter Type Required Description
input string/object Yes Input data for the model
agentId number No Agent ID for reputation tracking
labels string[] No Custom labels for classification models

Response Headers

On Success (200)

Header Description
X-PAYMENT-RESPONSE Base64-encoded payment result

Payment Response Decoded

{
  "success": true,
  "transaction": "0xabc123...",
  "network": "avalanche-fuji",
  "payer": "0xUserWallet...",
  "errorReason": null
}

Model Types

Sentiment Analysis

Input:

{
  "input": "The market is looking bullish today"
}

Output:

{
  "task": "sentiment-analysis",
  "sentiment": "positive",
  "confidence": 0.89,
  "all_scores": [
    { "label": "positive", "score": 0.89 },
    { "label": "neutral", "score": 0.08 },
    { "label": "negative", "score": 0.03 }
  ]
}

Zero-Shot Classification

Input:

{
  "input": "How do I stake my tokens?",
  "labels": ["DeFi", "NFT", "Security", "Governance"]
}

Output:

{
  "task": "zero-shot-classification",
  "labels": ["DeFi", "Governance", "Security", "NFT"],
  "scores": [0.72, 0.15, 0.08, 0.05],
  "top_label": "DeFi",
  "top_score": 0.72
}

Text Generation

Input:

{
  "input": "Explain smart contracts in simple terms"
}

Output:

{
  "task": "text2text-generation",
  "generated_text": "Smart contracts are self-executing programs..."
}


Error Responses

Payment Required (402)

{
  "x402Version": 1,
  "accepts": [{ ... }],
  "error": "X-PAYMENT header is required"
}

Payment Failed (402)

{
  "x402Version": 1,
  "accepts": [{ ... }],
  "error": "Insufficient USDC balance"
}

Model Not Found (404)

{
  "ok": false,
  "error": "model_not_found",
  "message": "Model 999 not found"
}

Rate Limited (429)

{
  "ok": false,
  "error": "rate_limited",
  "message": "Too many requests"
}

X-PAYMENT Header Format

The X-PAYMENT header contains a base64-encoded JSON payload:

{
  "x402Version": 1,
  "scheme": "exact",
  "network": "avalanche-fuji",
  "payload": {
    "signature": "0x...",
    "authorization": {
      "from": "0xUserWallet...",
      "to": "0xSplitterAddress...",
      "value": "10000",
      "validAfter": "1702300000",
      "validBefore": "1702300060",
      "nonce": "0x..."
    }
  }
}

Code Examples

JavaScript/TypeScript

async function runInference(modelId: number, input: string) {
  // Step 1: Get payment requirements
  const res1 = await fetch(`/api/inference/${modelId}`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ input })
  })

  if (res1.status !== 402) {
    return res1.json()
  }

  const { accepts } = await res1.json()
  const requirement = accepts[0]

  // Step 2: Build and sign payment
  const payment = await buildPayment(requirement)
  const xPayment = btoa(JSON.stringify(payment))

  // Step 3: Retry with payment
  const res2 = await fetch(`/api/inference/${modelId}`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-PAYMENT': xPayment
    },
    body: JSON.stringify({ input })
  })

  return res2.json()
}

Python

import requests
import base64
import json

def run_inference(model_id: int, input_text: str, payment: dict):
    url = f"https://wasiai.io/api/inference/{model_id}"

    # Step 1: Get requirements
    res1 = requests.post(url, json={"input": input_text})

    if res1.status_code != 402:
        return res1.json()

    # Step 2: Retry with payment
    x_payment = base64.b64encode(json.dumps(payment).encode()).decode()

    res2 = requests.post(
        url,
        json={"input": input_text},
        headers={"X-PAYMENT": x_payment}
    )

    return res2.json()

Rate Limits

Limit Value
Requests per minute 10
Max input size 10KB
Timeout 30 seconds