OrdianDocs
ordian.ai ↗

Authentication

Ordian Mail uses x402 micropayments instead of API keys. Pay per request with USDC on Base.

Overview

Unlike traditional APIs that require registration and API keys, Ordian Mail uses the x402 payment protocol. Every paid endpoint returns a 402 Payment Required response with payment instructions. Your agent signs an EIP-3009 USDC authorization, includes it in the request headers, and the request proceeds.

This means: no accounts, no API keys, no rate limit tiers. If you have a USDC wallet on Base, you can use the API.

Wallet setup

Before your agent can pay for API requests, it needs a wallet with USDC on Base. There are two approaches depending on your use case.

Option A: Private key (quick start)

The fastest way to get started. Generate or import a private key and use it directly with viem.

wallet-setup.ts
import { privateKeyToAccount } from "viem/accounts";

// Load from environment variable — never hardcode private keys
const signer = privateKeyToAccount(
  process.env.EVM_PRIVATE_KEY as `0x${string}`
);

console.log("Wallet address:", signer.address);
⚠️ WarningOnly use raw private keys for development and testing. For production agents, use a managed wallet solution like CDP Server Wallets (Option B) to avoid key exposure risks.

Option B: CDP Server Wallet (recommended)

Coinbase CDP Server Wallets provide managed key infrastructure — no raw key exposure, configurable spending policies, and built-in guardrails for autonomous agents.

Install
npm install @coinbase/cdp-sdk dotenv
cdp-wallet.ts
import { CdpClient } from "@coinbase/cdp-sdk";
import { toAccount } from "viem/accounts";
import dotenv from "dotenv";

dotenv.config();

// Requires CDP_API_KEY_ID, CDP_API_KEY_SECRET, CDP_WALLET_SECRET in .env
const cdp = new CdpClient();
const cdpAccount = await cdp.evm.createAccount();
const signer = toAccount(cdpAccount);

console.log("CDP wallet address:", signer.address);

CDP wallets are ideal for production agents: keys are managed server-side, you can set spending limits, and there's no risk of leaking a raw private key.

Funding your wallet

Your wallet needs two things on Base mainnet:

  • USDC — to pay for API requests. Contract: 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
  • ETH — a tiny amount for gas fees (very low on Base)

Ways to fund your wallet:

  • Coinbase — withdraw USDC directly to Base (free withdrawals, no bridge fees)
  • Bridge from Ethereum — use the Base Bridge to move USDC from Ethereum L1
  • DEX on Base — swap ETH for USDC on Uniswap, Aerodrome, or similar
💡 TipFor most agents, $5–10 of USDC is enough for thousands of API calls. Sending 100 emails costs just $1.00.

Setting up the x402 client

The x402 client libraries handle the full payment flow automatically: detect 402 responses, sign payments, and retry requests with the payment header. Install the packages for your language:

Node.js

Install
# Using fetch (recommended)
npm install @x402/fetch @x402/evm viem

# Or using axios
npm install @x402/axios @x402/evm viem

With @x402/fetch:

x402-fetch-setup.ts
import { x402Client, wrapFetchWithPayment } from "@x402/fetch";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";

const signer = privateKeyToAccount(
  process.env.EVM_PRIVATE_KEY as `0x${string}`
);

const client = new x402Client();
registerExactEvmScheme(client, { signer });

// Wrap native fetch — all 402 responses are handled automatically
const fetchWithPayment = wrapFetchWithPayment(fetch, client);

With @x402/axios:

x402-axios-setup.ts
import { x402Client, withPaymentInterceptor } from "@x402/axios";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
import axios from "axios";

const signer = privateKeyToAccount(
  process.env.EVM_PRIVATE_KEY as `0x${string}`
);

const client = new x402Client();
registerExactEvmScheme(client, { signer });

// Wrap axios instance — 402 interceptor handles payments
const api = withPaymentInterceptor(
  axios.create({ baseURL: "https://mail-api.ordian.ai" }),
  client
);

Python

Install
# For httpx (async) — recommended
pip install "x402[httpx,evm]" eth_account

# For requests (sync)
pip install "x402[requests,evm]" eth_account
x402-python-setup.py
import os
from eth_account import Account
from x402 import x402Client
from x402.http.clients import x402HttpxClient
from x402.mechanisms.evm import EthAccountSigner
from x402.mechanisms.evm.exact.register import register_exact_evm_client

# Create signer from private key
account = Account.from_key(os.getenv("EVM_PRIVATE_KEY"))
signer = EthAccountSigner(account)

# Create x402 client and register EVM scheme
client = x402Client()
register_exact_evm_client(client, signer)

# Use the httpx client — 402 payments are handled automatically
async with x402HttpxClient(client) as http:
    response = await http.post(
        "https://mail-api.ordian.ai/v1/inboxes",
        json={"display_name": "My Agent"}
    )

Payment flow

Under the hood, the x402 client handles a 4-step flow. You only need to understand this if you're implementing the protocol manually.

Step 1: Make a request without payment

curl -X POST https://mail-api.ordian.ai/v1/send \
  -H "Content-Type: application/json" \
  -d '{"inbox_id": "...", "to": "...", "subject": "...", "text": "..."}'

Step 2: Receive 402 response

The server responds with payment instructions:

{
  "x402Version": 1,
  "accepts": [
    {
      "scheme": "exact",
      "network": "base",
      "maxAmountRequired": "10000",
      "resource": "POST /v1/send",
      "description": "Send an email from an agent inbox",
      "payTo": "0x...",
      "maxTimeoutSeconds": 300
    }
  ],
  "error": "X-PAYMENT header is required"
}

Step 3: Sign payment

Your agent signs an EIP-3009 transferWithAuthorization for the USDC amount specified. This authorizes the transfer without actually moving funds until the server settles.

Step 4: Retry with payment header

curl -X POST https://mail-api.ordian.ai/v1/send \
  -H "Content-Type: application/json" \
  -H "X-PAYMENT: <base64-encoded-payment-payload>" \
  -d '{"inbox_id": "...", "to": "...", "subject": "...", "text": "..."}'

The server validates the payment, settles the USDC transfer, and processes your request.

💡 TipUse an x402 client library (@x402/fetch, @x402/axios, or the Python x402 package) to handle this flow automatically. See Code Examples for complete working examples.

Network

Ordian Mail operates on Base mainnet (Coinbase L2). Payments are in USDC. Gas costs on Base are negligible — typically very low per transaction.

Free endpoints

Some endpoints don't require payment:

  • GET /health — service health check
  • GET /skill.md — Agent Skills file download
  • DELETE /v1/inboxes/:id — delete an inbox
  • GET /v1/webhooks — list webhooks
  • POST /v1/domains/:id/verify — verify domain DNS