{
  "name": "XE Testnet node API",
  "description": "JSON HTTP API of the public London XE testnet node, proxied at https://test.network/api/v1. Every XE node exposes the same API.",
  "version": "1.0.0",
  "major_version": 1,
  "network": "testnet-0001",
  "openapi": "https://test.network/openapi.json",
  "docs": "https://test.network/docs/api",
  "developers": "https://test.network/developers",
  "llms": "https://test.network/llms.txt",
  "servers": [
    {
      "url": "https://test.network/api/v1",
      "description": "test.network proxy, versioned (pin this)"
    },
    {
      "url": "https://test.network/api",
      "description": "test.network proxy, alias of the current major version"
    },
    {
      "url": "https://ldn.test.network/api",
      "description": "London testnet node (direct, unversioned)"
    }
  ],
  "upstream_manifest": "https://ldn.test.network/api/",
  "versioning": {
    "scheme": "url-path",
    "current": "v1",
    "versionedBase": "https://test.network/api/v1",
    "unversionedBase": "https://test.network/api",
    "docs": "https://test.network/developers#versioning",
    "rules": [
      "The version is the first path segment after /api: https://test.network/api/v1/node. Every response also carries X-API-Version: 1.",
      "Unversioned paths (https://test.network/api/node) are an alias for the current major version and follow it when it changes; integrations that must not move pin the versioned path.",
      "Within a major version changes are additive only: new endpoints, new optional fields, new enum values. Clients must ignore fields they do not know. Removing or renaming a field, changing a type, or changing an endpoint's meaning happens only in a new major version.",
      "When a new major version ships, the previous one keeps working for at least 180 days.",
      "Deprecated endpoints and versions are announced in the OpenAPI document (`deprecated: true`) and on every response with a Deprecation header (RFC 9745, `Deprecation: @<unix-seconds>`), a Sunset header (RFC 8594, HTTP-date of removal) and a `Link: <url>; rel=\"deprecation\"` pointing at the migration notes. Sunset is never less than 90 days after the Deprecation date.",
      "Testnet wipes reset ledger state, not the API: identifiers change, the contract does not.",
      "The direct node endpoint https://ldn.test.network/api is unversioned and tracks the node release; the versioned contract is the https://test.network/api surface described by https://test.network/openapi.json."
    ]
  },
  "auth": {
    "default": "none",
    "admin": "Authorization: Bearer <XE_API_ADMIN_TOKEN> — operator-only (POST /lease/request, unfiltered GET /chat/events).",
    "ownership_proof": "Chat reads: account, pub_key, challenge (GET /chat/auth/challenge) and sig query parameters."
  },
  "rate_limits": {
    "docs": "https://test.network/developers#rate-limits",
    "scope": "per client IP, per class",
    "policies": [
      {
        "name": "read",
        "quota": 1000,
        "window_seconds": 5,
        "description": "GET and HEAD requests: 1,000 per 5 seconds per client IP (200/s sustained)."
      },
      {
        "name": "write",
        "quota": 50,
        "window_seconds": 5,
        "description": "POST, PUT, PATCH and DELETE requests: 50 per 5 seconds per client IP (10/s sustained)."
      }
    ],
    "headers": {
      "RateLimit-Policy": "the policy in force, e.g. \"read\";q=1000;w=5",
      "RateLimit": "remaining quota and seconds to reset, e.g. \"read\";r=998;t=4",
      "RateLimit-Limit": "quota (legacy form)",
      "RateLimit-Remaining": "remaining (legacy form)",
      "RateLimit-Reset": "seconds to reset (legacy form)",
      "Retry-After": "on 429 only: seconds to wait"
    },
    "on_exceeded": "HTTP 429 with a JSON Error body (code rate_limited) and Retry-After."
  },
  "units": "All amounts are integer micro-units: 1 XE = 1 XUSD = 1,000,000 micro-units.",
  "errors": {
    "format": "application/json",
    "schema": "https://test.network/openapi.json#/components/schemas/Error",
    "codes": [
      "bad_request",
      "unauthorized",
      "forbidden",
      "not_found",
      "method_not_allowed",
      "rate_limited",
      "upstream_error",
      "upstream_unavailable",
      "upstream_timeout"
    ]
  },
  "response_headers": {
    "X-API-Version": "major version that served the request (currently 1)"
  },
  "endpoints": [
    {
      "operationId": "listAccounts",
      "method": "GET",
      "path": "/accounts",
      "summary": "List all accounts",
      "auth": "none",
      "url": "https://test.network/api/v1/accounts"
    },
    {
      "operationId": "getAccountBalance",
      "method": "GET",
      "path": "/accounts/{address}/balance",
      "summary": "Get account balance",
      "auth": "none",
      "url": "https://test.network/api/v1/accounts/{address}/balance"
    },
    {
      "operationId": "getAccountChain",
      "method": "GET",
      "path": "/accounts/{address}/chain",
      "summary": "Get account chain",
      "auth": "none",
      "url": "https://test.network/api/v1/accounts/{address}/chain"
    },
    {
      "operationId": "getAccountKeyset",
      "method": "GET",
      "path": "/accounts/{address}/keyset",
      "summary": "Get multisig keyset",
      "auth": "none",
      "url": "https://test.network/api/v1/accounts/{address}/keyset"
    },
    {
      "operationId": "getAccountReputation",
      "method": "GET",
      "path": "/accounts/{address}/reputation",
      "summary": "Get account reputation",
      "auth": "none",
      "url": "https://test.network/api/v1/accounts/{address}/reputation"
    },
    {
      "operationId": "listReputations",
      "method": "GET",
      "path": "/reputation",
      "summary": "All reputations",
      "auth": "none",
      "url": "https://test.network/api/v1/reputation"
    },
    {
      "operationId": "submitSendBlock",
      "method": "POST",
      "path": "/blocks/send",
      "summary": "Submit send block",
      "auth": "none",
      "url": "https://test.network/api/v1/blocks/send"
    },
    {
      "operationId": "submitReceiveBlock",
      "method": "POST",
      "path": "/blocks/receive",
      "summary": "Submit receive block",
      "auth": "none",
      "url": "https://test.network/api/v1/blocks/receive"
    },
    {
      "operationId": "submitLeaseBlock",
      "method": "POST",
      "path": "/blocks/lease",
      "summary": "Submit lease block",
      "auth": "none",
      "url": "https://test.network/api/v1/blocks/lease"
    },
    {
      "operationId": "submitLeaseAcceptBlock",
      "method": "POST",
      "path": "/blocks/lease_accept",
      "summary": "Submit lease accept",
      "auth": "none",
      "url": "https://test.network/api/v1/blocks/lease_accept"
    },
    {
      "operationId": "submitLeaseSettleBlock",
      "method": "POST",
      "path": "/blocks/lease_settle",
      "summary": "Submit lease settle",
      "auth": "none",
      "url": "https://test.network/api/v1/blocks/lease_settle"
    },
    {
      "operationId": "submitLeaseCancelBlock",
      "method": "POST",
      "path": "/blocks/lease_cancel",
      "summary": "Submit lease cancel",
      "auth": "none",
      "url": "https://test.network/api/v1/blocks/lease_cancel"
    },
    {
      "operationId": "submitLeaseForceSettleBlock",
      "method": "POST",
      "path": "/blocks/lease_force_settle",
      "summary": "Submit lease force settle",
      "auth": "none",
      "url": "https://test.network/api/v1/blocks/lease_force_settle"
    },
    {
      "operationId": "submitMultisigOpenBlock",
      "method": "POST",
      "path": "/blocks/multisig_open",
      "summary": "Open multisig account",
      "auth": "none",
      "url": "https://test.network/api/v1/blocks/multisig_open"
    },
    {
      "operationId": "submitMultisigUpdateBlock",
      "method": "POST",
      "path": "/blocks/multisig_update",
      "summary": "Update multisig keyset",
      "auth": "none",
      "url": "https://test.network/api/v1/blocks/multisig_update"
    },
    {
      "operationId": "submitBurnBlock",
      "method": "POST",
      "path": "/blocks/burn",
      "summary": "Submit burn block",
      "auth": "none",
      "url": "https://test.network/api/v1/blocks/burn"
    },
    {
      "operationId": "submitMintBlock",
      "method": "POST",
      "path": "/blocks/mint",
      "summary": "Submit mint block",
      "auth": "none",
      "url": "https://test.network/api/v1/blocks/mint"
    },
    {
      "operationId": "getBlock",
      "method": "GET",
      "path": "/blocks/{hash}",
      "summary": "Get block by hash",
      "auth": "none",
      "url": "https://test.network/api/v1/blocks/{hash}"
    },
    {
      "operationId": "listRecentBlocks",
      "method": "GET",
      "path": "/blocks/recent",
      "summary": "Recent blocks",
      "auth": "none",
      "url": "https://test.network/api/v1/blocks/recent"
    },
    {
      "operationId": "listLeases",
      "method": "GET",
      "path": "/leases",
      "summary": "List leases",
      "auth": "none",
      "url": "https://test.network/api/v1/leases"
    },
    {
      "operationId": "getLease",
      "method": "GET",
      "path": "/leases/{hash}",
      "summary": "Get lease",
      "auth": "none",
      "url": "https://test.network/api/v1/leases/{hash}"
    },
    {
      "operationId": "listProviders",
      "method": "GET",
      "path": "/providers",
      "summary": "List providers",
      "auth": "none",
      "url": "https://test.network/api/v1/providers"
    },
    {
      "operationId": "getNodeCertificate",
      "method": "GET",
      "path": "/certificate",
      "summary": "Node perf certificate",
      "auth": "none",
      "url": "https://test.network/api/v1/certificate"
    },
    {
      "operationId": "getProviderCertificate",
      "method": "GET",
      "path": "/certificate/{provider}",
      "summary": "Provider perf certificate",
      "auth": "none",
      "url": "https://test.network/api/v1/certificate/{provider}"
    },
    {
      "operationId": "requestLease",
      "method": "POST",
      "path": "/lease/request",
      "summary": "Request lease",
      "auth": "admin",
      "url": "https://test.network/api/v1/lease/request"
    },
    {
      "operationId": "requestAttestation",
      "method": "POST",
      "path": "/attestation/request",
      "summary": "Request attestation",
      "auth": "none",
      "url": "https://test.network/api/v1/attestation/request"
    },
    {
      "operationId": "listVms",
      "method": "GET",
      "path": "/vms",
      "summary": "List VMs",
      "auth": "none",
      "url": "https://test.network/api/v1/vms"
    },
    {
      "operationId": "getVm",
      "method": "GET",
      "path": "/vms/{lease}",
      "summary": "Get VM",
      "auth": "none",
      "url": "https://test.network/api/v1/vms/{lease}"
    },
    {
      "operationId": "openTcpTunnel",
      "method": "POST",
      "path": "/tunnel/{leaseHash}/tcp",
      "summary": "TCP tunnel",
      "auth": "lease-signature",
      "url": "https://test.network/api/v1/tunnel/{leaseHash}/tcp"
    },
    {
      "operationId": "getStateChainTip",
      "method": "GET",
      "path": "/statechain/tip",
      "summary": "State chain tip",
      "auth": "none",
      "url": "https://test.network/api/v1/statechain/tip"
    },
    {
      "operationId": "getStateBlock",
      "method": "GET",
      "path": "/statechain/blocks/{index}",
      "summary": "State block by index",
      "auth": "none",
      "url": "https://test.network/api/v1/statechain/blocks/{index}"
    },
    {
      "operationId": "listStateBlocks",
      "method": "GET",
      "path": "/statechain/blocks",
      "summary": "State blocks",
      "auth": "none",
      "url": "https://test.network/api/v1/statechain/blocks"
    },
    {
      "operationId": "getStateValue",
      "method": "GET",
      "path": "/statechain/kv/{key}",
      "summary": "State value",
      "auth": "none",
      "url": "https://test.network/api/v1/statechain/kv/{key}"
    },
    {
      "operationId": "listStateValues",
      "method": "GET",
      "path": "/statechain/kv",
      "summary": "All state values",
      "auth": "none",
      "url": "https://test.network/api/v1/statechain/kv"
    },
    {
      "operationId": "getDaoKeyset",
      "method": "GET",
      "path": "/statechain/keyset",
      "summary": "DAO keyset",
      "auth": "none",
      "url": "https://test.network/api/v1/statechain/keyset"
    },
    {
      "operationId": "submitStateBlock",
      "method": "POST",
      "path": "/statechain/blocks",
      "summary": "Submit state block",
      "auth": "none",
      "url": "https://test.network/api/v1/statechain/blocks"
    },
    {
      "operationId": "registerDirectoryEntry",
      "method": "POST",
      "path": "/directory/register",
      "summary": "Register directory entry",
      "auth": "none",
      "url": "https://test.network/api/v1/directory/register"
    },
    {
      "operationId": "listDirectory",
      "method": "GET",
      "path": "/directory",
      "summary": "List directory",
      "auth": "none",
      "url": "https://test.network/api/v1/directory"
    },
    {
      "operationId": "getDirectoryEntry",
      "method": "GET",
      "path": "/directory/{account}",
      "summary": "Lookup directory entry",
      "auth": "none",
      "url": "https://test.network/api/v1/directory/{account}"
    },
    {
      "operationId": "sendChatMessage",
      "method": "POST",
      "path": "/chat/send",
      "summary": "Send chat message",
      "auth": "none",
      "url": "https://test.network/api/v1/chat/send"
    },
    {
      "operationId": "getChatAuthChallenge",
      "method": "GET",
      "path": "/chat/auth/challenge",
      "summary": "Chat auth challenge",
      "auth": "none",
      "url": "https://test.network/api/v1/chat/auth/challenge"
    },
    {
      "operationId": "listChatMessages",
      "method": "GET",
      "path": "/chat/messages",
      "summary": "Chat messages",
      "auth": "ownership-proof",
      "url": "https://test.network/api/v1/chat/messages"
    },
    {
      "operationId": "listChatContacts",
      "method": "GET",
      "path": "/chat/contacts",
      "summary": "Chat contacts",
      "auth": "none",
      "url": "https://test.network/api/v1/chat/contacts"
    },
    {
      "operationId": "streamChatEvents",
      "method": "GET",
      "path": "/chat/events",
      "summary": "Chat event stream",
      "auth": "ownership-proof",
      "url": "https://test.network/api/v1/chat/events"
    },
    {
      "operationId": "getNodeInfo",
      "method": "GET",
      "path": "/node",
      "summary": "Node info",
      "auth": "none",
      "url": "https://test.network/api/v1/node"
    },
    {
      "operationId": "listPendingForAccount",
      "method": "GET",
      "path": "/pending/{address}",
      "summary": "Pending for account",
      "auth": "none",
      "url": "https://test.network/api/v1/pending/{address}"
    },
    {
      "operationId": "listPending",
      "method": "GET",
      "path": "/pending",
      "summary": "All pending sends",
      "auth": "none",
      "url": "https://test.network/api/v1/pending"
    },
    {
      "operationId": "listFrontiers",
      "method": "GET",
      "path": "/frontiers",
      "summary": "Frontiers",
      "auth": "none",
      "url": "https://test.network/api/v1/frontiers"
    },
    {
      "operationId": "getDelegation",
      "method": "GET",
      "path": "/delegation",
      "summary": "Delegation weights",
      "auth": "none",
      "url": "https://test.network/api/v1/delegation"
    },
    {
      "operationId": "listConflicts",
      "method": "GET",
      "path": "/conflicts",
      "summary": "Conflicts",
      "auth": "none",
      "url": "https://test.network/api/v1/conflicts"
    },
    {
      "operationId": "listConflictsForAccount",
      "method": "GET",
      "path": "/conflicts/{account}",
      "summary": "Conflicts for account",
      "auth": "none",
      "url": "https://test.network/api/v1/conflicts/{account}"
    }
  ]
}