Documentation

Arcus facilitator

A public x402 v2 facilitator for the exact scheme on Arc. It verifies EIP-3009 USDC authorizations and settles them on-chain. No account or API key needed.

https://facilitator.arcusnetwork.io

Quickstart

Install the x402 server packages, register the exact EVM scheme for Arc and point the facilitator client at Arcus. Arc has no SDK default asset yet, so price routes with an explicit USDC amount.

terminal
sh
npm i @x402/express @x402/core @x402/evm
server.ts
ts
import express from 'express';
import { paymentMiddleware } from '@x402/express';
import { x402ResourceServer, HTTPFacilitatorClient } from '@x402/core/server';
import { ExactEvmScheme } from '@x402/evm/exact/server';

const facilitator = new HTTPFacilitatorClient({
  url: 'https://facilitator.arcusnetwork.io',
});

const server = new x402ResourceServer(facilitator)
  .register('eip155:5042', new ExactEvmScheme());

const app = express();

app.use(paymentMiddleware({
  'GET /weather': {
    accepts: {
      scheme: 'exact',
      network: 'eip155:5042',          // Arc mainnet
      payTo: '0xYourMerchantAddress',
      price: {
        amount: '10000',               // 0.01 USDC (6 decimals)
        asset: '0x3600000000000000000000000000000000000000',
        extra: { name: 'USDC', version: '2' },
      },
    },
    description: 'Current weather',
  },
}, server));

app.get('/weather', (_req, res) => res.json({ temp: 24 }));
app.listen(4021);

On the paying side, any x402 v2 client works. Arc USDC is not yet one of the SDK's default assets, so allowlist it in spendControls.

agent.ts
ts
import { privateKeyToAccount } from 'viem/accounts';
import { x402Client, wrapFetchWithPayment } from '@x402/fetch';
import { ExactEvmScheme } from '@x402/evm/exact/client';

const account = privateKeyToAccount(process.env.AGENT_KEY as `0x${string}`);
const USDC = '0x3600000000000000000000000000000000000000';

// Arc USDC isn't an SDK default asset yet — allowlist it explicitly.
const client = x402Client.fromConfig({
  schemes: [{ network: 'eip155:5042', client: new ExactEvmScheme(account) }],
  spendControls: {
    allowedAssets: [
      { network: 'eip155:5042', asset: USDC, maxAmountPerPayment: '1000000' }, // ≤ 1 USDC
    ],
  },
});

const pay = wrapFetchWithPayment(fetch, client);
const res = await pay('https://api.example.com/weather');
Testing? Use eip155:5042002 and get testnet USDC from the Circle faucet.

Networks

Arc MainnetMainnet
CAIP-2
eip155:5042
Chain ID
5042
USDC
0x3600000000000000000000000000000000000000
Decimals
6
EIP-712 domain
name "USDC", version "2"
Explorer
www.arcexplorer.org
Arc TestnetTestnet
CAIP-2
eip155:5042002
Chain ID
5042002
USDC
0x3600000000000000000000000000000000000000
Decimals
6
EIP-712 domain
name "USDC", version "2"
Explorer
testnet.arcscan.app

List supported kinds

GET/supported

Returns the payment kinds Arcus accepts and the relayer address that submits settlements.

request
sh
curl https://facilitator.arcusnetwork.io/supported
200 OK
json
{
  "kinds": [
    { "x402Version": 2, "scheme": "exact", "network": "eip155:5042" },
    { "x402Version": 2, "scheme": "exact", "network": "eip155:5042002" }
  ],
  "extensions": [],
  "signers": { "eip155:*": ["0xRelayer"] }
}

Verify a payment

POST/verify

Checks the signature, amount, recipient, validity window and payer balance. It does not change chain state, so call it before doing expensive work.

request
http
POST https://facilitator.arcusnetwork.io/verify
Content-Type: application/json

{
  "x402Version": 2,
  "paymentPayload": {
    "x402Version": 2,
    "accepted": { /* the requirement the client chose */ },
    "payload": {
      "authorization": {
        "from": "0xPayer", "to": "0xMerchant",
        "value": "10000",
        "validAfter": "0", "validBefore": "1760000000",
        "nonce": "0x…"
      },
      "signature": "0x…"
    }
  },
  "paymentRequirements": {
    "scheme": "exact",
    "network": "eip155:5042",
    "amount": "10000",
    "asset": "0x3600000000000000000000000000000000000000",
    "payTo": "0xMerchant",
    "maxTimeoutSeconds": 60,
    "extra": { "name": "USDC", "version": "2" }
  }
}
200 OK
json
{ "isValid": true, "payer": "0xPayer" }

Settle a payment

POST/settle

Same body as /verify. Arcus re-verifies, simulates, then submits transferWithAuthorization and waits up to 60 s for the receipt. USDC moves directly from payer to payTo.

200 OK
json
{
  "success": true,
  "payer": "0xPayer",
  "transaction": "0x5b1c…e9a2",
  "network": "eip155:5042"
}

Errors & limits

ReasonMeaning
malformed_requestBody failed x402 v2 schema validation.
unsupported_x402_versionOnly x402Version 2 payloads are accepted.
unsupported_networkRequirements must target eip155:5042 or eip155:5042002.
rate_limited120 requests per minute per IP, per endpoint.
invalid_exact_evm_*Signature, amount, recipient, time window or balance check failed.
unexpected_*_errorRPC or relayer problem — safe to retry.

Network health is published at /health and on the status page.