Skip to main content
x402 agent endpoints are in beta. For the full flow and reference scripts, see x402 Agent Subscription and Top-Up.
Agents only. This endpoint is for agents (wallet-based, programmatic access). Dashboard customers manage API keys at admin.mobula.io, not via this x402 endpoint.
DELETE /x402/agent/api-keys/revoke revokes (soft-deletes) an API key that belongs to your agent. The key must belong to the same agent as the paying wallet. Cost: $0.001 USDC (facilitator fee). You must have an active plan.

Query parameters

ParameterRequiredDescription
api_keyYesThe API key to revoke (must belong to this agent)

Request flow

  1. Call DELETE /x402/agent/api-keys/revoke?api_key=<key> with no payment → 402 Payment Required with $0.001 USDC.
  2. Sign the payment and retry with an x-payment header → 200 OK with { "deleted": true }.
404 — No agent for this wallet, or the given api_key does not belong to this agent.

Reference scripts

Uses the same wallet as for subscribe. Set API_KEY to the key you want to revoke.
Prerequisites: Solana wallet with USDC for $0.001 and SOL for fees.Full script (uses @solana/kit, @x402/core, @x402/svm). Inline base58ToBytes below, or use import { base58ToBytes } from './base58.ts' when running from scripts/src/x402/.
import { createKeyPairSignerFromBytes } from '@solana/kit';
import { x402Client, x402HTTPClient } from '@x402/core/client';
import { registerExactSvmScheme } from '@x402/svm/exact/client';

const BASE_URL = process.env.API_URL ?? 'http://localhost:4058';
const PRIVATE_KEY_B58 = process.env.SOLANA_PRIVATE_KEY;
const API_KEY = process.env.API_KEY;

function base58ToBytes(b58: string): Uint8Array {
  const ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
  const map = new Uint8Array(256).fill(255);
  for (let i = 0; i < ALPHABET.length; i++) map[ALPHABET.charCodeAt(i)] = i;
  const bytes: number[] = [0];
  for (const char of b58) {
    const value = map[char.charCodeAt(0)];
    if (value === undefined || value === 255) throw new Error(`Invalid base58: ${char}`);
    let carry: number = value;
    for (let j = bytes.length - 1; j >= 0; j--) {
      carry += (bytes[j] as number) * 58;
      bytes[j] = carry & 0xff;
      carry >>= 8;
    }
    while (carry > 0) {
      bytes.unshift(carry & 0xff);
      carry >>= 8;
    }
  }
  for (const char of b58) {
    if (char !== '1') break;
    bytes.unshift(0);
  }
  return new Uint8Array(bytes);
}

async function main() {
  if (!PRIVATE_KEY_B58) {
    console.error('SOLANA_PRIVATE_KEY required');
    process.exit(1);
  }
  if (!API_KEY?.trim()) {
    console.error('API_KEY required');
    process.exit(1);
  }

  const signer = await createKeyPairSignerFromBytes(base58ToBytes(PRIVATE_KEY_B58));
  const endpoint = `/x402/agent/api-keys/revoke?api_key=${encodeURIComponent(API_KEY)}`;

  const probeRes = await fetch(`${BASE_URL}${endpoint}`, { method: 'DELETE' });
  if (probeRes.status !== 402) {
    console.error(probeRes.status, await probeRes.text());
    process.exit(1);
  }

  const paymentRequiredHeader = probeRes.headers.get('payment-required');
  if (!paymentRequiredHeader) {
    console.error('Missing payment-required header');
    process.exit(1);
  }

  const decoded = JSON.parse(Buffer.from(paymentRequiredHeader, 'base64').toString('utf-8'));
  const svmOption = decoded.accepts?.find((a: { network: string }) => a.network?.startsWith('solana:'));
  if (!svmOption) {
    console.error('No Solana option in 402');
    process.exit(1);
  }

  const client = new x402Client();
  registerExactSvmScheme(client, { signer });
  const httpClient = new x402HTTPClient(client);
  const paymentRequired = httpClient.getPaymentRequiredResponse((name) => probeRes.headers.get(name), decoded);

  let paymentHeaders: Record<string, string>;
  try {
    const payload = await httpClient.createPaymentPayload(paymentRequired);
    paymentHeaders = httpClient.encodePaymentSignatureHeader(payload);
  } catch (err) {
    console.error('Payment failed:', err);
    process.exit(1);
  }

  const paidRes = await fetch(`${BASE_URL}${endpoint}`, { method: 'DELETE', headers: paymentHeaders });
  const body = await paidRes.text();

  if (paidRes.status !== 200) {
    console.error(paidRes.status, body);
    process.exit(1);
  }

  console.log(body);
  process.exit(0);
}

main().catch((err) => {
  console.error(err);
  process.exit(1);
});

To create a new API key: Create Agent API Key. Full walkthrough: x402 Agent Subscription and Top-Up.