x402 APIs
Paid per-call data APIs for XDC Network: Plugin feed safety verdicts, ComTech Gold (CGO) reserve-report facts, and masternode and Plugin node health. All data is read from public XDC mainnet contracts and RPC, or computed by FeedPlumb.
$BASE stands for its address.| Base path | $BASE/x402 · Hosted API coming soon. $BASE stands for its address, which is published at launch; these requests do not work yet. |
|---|---|
| Authentication | A registered B2B API key in the X-FeedPlumb-Key header. Keys are issued by FeedPlumb to registered businesses; there is no self-signup. Requesting access: Coming soon. |
| Payment | Each paid request uses x402: without payment the API answers HTTP 402 with the payment requirements, and the client repeats the request with an X-PAYMENT payload. Paid access: Coming soon. No payments are taken yet. Usage is invoiced monthly per key. Prices: Coming soon. |
| Limits | Per-key rate limit (requests per minute, set per key); headers X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. Chain reads are cached up to 15 s. |
| Health | /x402/health · status page |
How access and payment work
- Use the registered B2B API key FeedPlumb issued to your business in the
X-FeedPlumb-Keyheader. Without a valid key the API answers 401; a revoked key gets 403. - Call the endpoint. Input is checked first (400 or 404, nothing to pay), then the API answers
402 Payment Requiredwith an x402 body:x402Versionandaccepts, which listsscheme,network,maxAmountRequired(price in atomic units of the payment asset),resource,payTo,assetandmaxTimeoutSeconds. - Repeat the same request with an
X-PAYMENTheader: a base64 JSON payment payload for those requirements. Each payload can be used once. - On success you get 200 with the data and an
X-PAYMENT-RESPONSEheader (base64 JSON receipt). If the chain read fails you get 502, the payment is not settled and the call is not billed. - Every paid call is recorded against your key ID and listed on a monthly summary invoice.
Paid access: Coming soon. No payments are taken yet.
GET /x402/v1/feed/{address}/verdictauth: B2B key + x402
Reads latestRoundData, decimals, description and the aggregator settings of a Plugin feed proxy and applies fixed rules: pass only if the feed is fresh, the answer is positive and the round is complete. Lists other proxies for the same pair and which one to prefer. The feed's answer value is not returned.
| Parameter | Description |
|---|---|
address | Plugin feed proxy address |
maxAgeS | Freshness limit in seconds (60 to 2592000, default 86400) (optional) |
# 1) without payment: 402 with the payment requirements
curl -s "$BASE/x402/v1/feed/0x2baa1AEfa06D58454c9c06C56436CdD5B7904248/verdict" -H "X-FeedPlumb-Key: $FEEDPLUMB_KEY"
# 2) with the x402 payment payload
curl -s "$BASE/x402/v1/feed/0x2baa1AEfa06D58454c9c06C56436CdD5B7904248/verdict" -H "X-FeedPlumb-Key: $FEEDPLUMB_KEY" -H "X-PAYMENT: $PAYMENT"{
"proxy": "0x2baa1AEfa06D58454c9c06C56436CdD5B7904248",
"pair": "PLI/USDT",
"description": "PLI/USDT",
"verdict": "pass",
"status": "fresh",
"ageS": 554,
"maxAgeS": 86400,
"reasons": [],
"warnings": [],
"round": {
"roundId": "18446744073709600709",
"answeredInRound": "18446744073709600709",
"updatedAt": 1792740681,
"updatedAtIso": "2026-10-23T07:31:21.000Z",
"answerPositive": true
},
"decimals": 16,
"aggregator": "0x499b32df5da30f5c531180aadc7a32e208d86e7d",
"oracles": {
"minSubmissionCount": 2,
"maxSubmissionCount": 4,
"oracleCount": 4,
"latestRound": 49093,
"roundTimeoutS": 60
},
"samePairProxies": [],
"preferredProxy": "0x2baa1AEfa06D58454c9c06C56436CdD5B7904248",
"source": {
"chainId": 50,
"block": 108633587,
"blockTime": 1792741235,
"blockTimeIso": "2026-10-23T07:40:35.000Z",
"methods": [
"latestRoundData()",
"decimals()",
"description()",
"aggregator()",
"minSubmissionCount()",
"maxSubmissionCount()",
"getOracles()",
"latestRound()",
"timeout()"
]
},
"rules": {
"status": "reverting if latestRoundData() fails; stale if block time - updatedAt > maxAgeS (default 86400); otherwise fresh",
"pass": "verdict is pass only if status is fresh AND answer > 0 AND answeredInRound >= roundId AND updatedAt is not in the future",
"warnings": "single-oracle quorum (minSubmissionCount < 2), oracle count below max, another proxy for the same pair is fresher"
},
"disclaimer": "Facts read from public XDC mainnet contracts with a fixed rule set. Not financial advice and not a guarantee of future feed behaviour.",
"listedSourceCount": 4
}GET /x402/v1/verdictsauth: B2B key + x402
Same rules as the single verdict, for every known Plugin proxy of the pair, plus the preferred proxy.
| Parameter | Description |
|---|---|
pair | Pair, BASE/QUOTE, for example USDC/USD |
maxAgeS | Freshness limit in seconds (60 to 2592000, default 86400) (optional) |
# 1) without payment: 402 with the payment requirements
curl -s "$BASE/x402/v1/verdicts?pair=USDC/USD" -H "X-FeedPlumb-Key: $FEEDPLUMB_KEY"
# 2) with the x402 payment payload
curl -s "$BASE/x402/v1/verdicts?pair=USDC/USD" -H "X-FeedPlumb-Key: $FEEDPLUMB_KEY" -H "X-PAYMENT: $PAYMENT"{
"pair": "USDC/USD",
"count": 2,
"preferredProxy": "0x1384E300f00641Cf617AC8B92c430B938eC8DC70",
"feeds": [
{
"proxy": "0x1384E300f00641Cf617AC8B92c430B938eC8DC70",
"pair": "USDC/USD",
"description": "USDC/USD",
"verdict": "pass",
"status": "fresh",
"ageS": 1243,
"maxAgeS": 86400,
"reasons": [],
"warnings": [
"single-oracle quorum: minSubmissionCount < 2"
],
"round": {
"roundId": "18446744073709562678",
"answeredInRound": "18446744073709562678",
"updatedAt": 1792739992,
"updatedAtIso": "2026-10-23T07:19:52.000Z",
"answerPositive": true
},
"decimals": 16,
"aggregator": "0xe5c7e623aca88acf0fe050bee4f29b9dededb9e2",
"oracles": {
"minSubmissionCount": 1,
"maxSubmissionCount": 1,
"oracleCount": 1,
"latestRound": 11062,
"roundTimeoutS": 60
},
"source": {
"chainId": 50,
"block": 108633587,
"blockTime": 1792741235,
"blockTimeIso": "2026-10-23T07:40:35.000Z",
"methods": [
"latestRoundData()",
"decimals()",
"description()",
"aggregator()",
"minSubmissionCount()",
"maxSubmissionCount()",
"getOracles()",
"latestRound()",
"timeout()"
]
},
"listedSourceCount": 1
},
{
"proxy": "0x6eaa502F038E98a0B04172455af10f173D0da913",
"pair": "USDC/USD",
"description": "USDC/USD",
"verdict": "fail",
"status": "stale",
"ageS": 91934511,
"maxAgeS": 86400,
"reasons": [
"last update 91934511 s before the latest block (limit 86400 s)"
],
"warnings": [
"single-oracle quorum: minSubmissionCount < 2"
],
"round": {
"roundId": "18446744073709551652",
"answeredInRound": "18446744073709551652",
"updatedAt": 1700806724,
"updatedAtIso": "2023-11-24T06:18:44.000Z",
"answerPositive": true
},
"decimals": 18,
"aggregator": "0x974aebd46c6c3707a5a5162e4e30a095844ffd66",
"oracles": {
"minSubmissionCount": 1,
"maxSubmissionCount": 1,
"oracleCount": 1,
"latestRound": 36,
"roundTimeoutS": 60
},
"source": {
"chainId": 50,
"block": 108633587,
"blockTime": 1792741235,
"blockTimeIso": "2026-10-23T07:40:35.000Z",
"methods": [
"latestRoundData()",
"decimals()",
"description()",
"aggregator()",
"minSubmissionCount()",
"maxSubmissionCount()",
"getOracles()",
"latestRound()",
"timeout()"
]
},
"listedSourceCount": 1
}
],
"rules": {
"status": "reverting if latestRoundData() fails; stale if block time - updatedAt > maxAgeS (default 86400); otherwise fresh",
"pass": "verdict is pass only if status is fresh AND answer > 0 AND answeredInRound >= roundId AND updatedAt is not in the future",
"warnings": "single-oracle quorum (minSubmissionCount < 2), oracle count below max, another proxy for the same pair is fresher"
},
"disclaimer": "Facts read from public XDC mainnet contracts with a fixed rule set. Not financial advice and not a guarantee of future feed behaviour.",
"source": {
"chainId": 50,
"block": 108633587,
"blockTime": 1792741235,
"blockTimeIso": "2026-10-23T07:40:35.000Z"
}
}GET /x402/v1/rwa/cgo/reserve-factsauth: B2B key + x402
On-chain CGO total supply, mint and burn events in about the last 24 hours, and the period and link of the latest reserve report listed on the issuer's website, with its age in days. Contains no gold price, valuation or price-feed data. Not an attestation.
# 1) without payment: 402 with the payment requirements
curl -s "$BASE/x402/v1/rwa/cgo/reserve-facts" -H "X-FeedPlumb-Key: $FEEDPLUMB_KEY"
# 2) with the x402 payment payload
curl -s "$BASE/x402/v1/rwa/cgo/reserve-facts" -H "X-FeedPlumb-Key: $FEEDPLUMB_KEY" -H "X-PAYMENT: $PAYMENT"{
"token": {
"symbol": "CGO",
"address": "0x8f9920283470f52128bf11b0c14e798be704fd15",
"chainId": 50,
"decimals": 18
},
"supply": {
"totalSupplyRaw": "24000000000000000000000",
"totalSupply": "24000",
"statedRatio": "1 CGO = 1 gram of gold (issuer statement, not verified by FeedPlumb)",
"gramsAtStatedRatio": "24000",
"window": {
"blocks": 43200,
"approxHours": 24,
"fromBlock": 108590387,
"toBlock": 108633587
},
"mintedInWindow": "0",
"burnedInWindow": "0",
"mintEvents": 0,
"burnEvents": 0
},
"latestReport": {
"periodFrom": "2023-10-12",
"periodTo": "2025-03-21",
"ageDays": 581,
"documentUrl": "https://cgold.ae/assets/pdf/Audit_file_21032025.pdf",
"publisher": "issuer website",
"listedOn": "https://cgold.ae/Routine",
"listCheckedAt": "2026-10-23"
},
"flags": [
"latest_listed_report_period_ended_over_365_days_ago"
],
"disclaimer": "Facts only: on-chain token supply and the date and link of the latest reserve report listed by the issuer. Not an attestation, not a price or benchmark, and no opinion on backing.",
"source": {
"chainId": 50,
"block": 108633587,
"blockTime": 1792741235,
"blockTimeIso": "2026-10-23T07:40:35.000Z",
"methods": [
"totalSupply()",
"decimals()",
"symbol()",
"Transfer logs from/to 0x0"
]
}
}GET /x402/v1/masternode/{address}/healthauth: B2B key + x402
XDPoS role (masternode, standby, penalized or unlisted), blocks since the node last produced a block and missed rounds this epoch, from public XDPoS RPC.
| Parameter | Description |
|---|---|
address | Masternode (coinbase) address |
# 1) without payment: 402 with the payment requirements
curl -s "$BASE/x402/v1/masternode/0x2f6802e8379d06cac135e9296f0b5b4132da1bd4/health" -H "X-FeedPlumb-Key: $FEEDPLUMB_KEY"
# 2) with the x402 payment payload
curl -s "$BASE/x402/v1/masternode/0x2f6802e8379d06cac135e9296f0b5b4132da1bd4/health" -H "X-FeedPlumb-Key: $FEEDPLUMB_KEY" -H "X-PAYMENT: $PAYMENT"{
"address": "0x2f6802e8379d06cac135e9296f0b5b4132da1bd4",
"addressXdc": "xdc2f6802e8379d06cac135e9296f0b5b4132da1bd4",
"status": "healthy",
"role": "masternode",
"reasons": [],
"signing": {
"lastProducedBlock": 108633551,
"blocksSinceLastProduced": 39,
"lagLimitBlocks": 216,
"scannedBlocks": 324,
"missedRoundsThisEpoch": 0,
"missedRoundsLimit": 3,
"method": "approximate: blocks since last produced block + missed rounds this epoch (vote signatures not decoded)"
},
"network": {
"masternodes": 108,
"standby": 255,
"penalized": 5
},
"notCovered": [
"client version / fork readiness (needs the operator's own RPC)"
],
"source": {
"chainId": 50,
"block": 108633590,
"blockTime": 1792741241,
"blockTimeIso": "2026-10-23T07:40:41.000Z",
"methods": [
"XDPoS_getMasternodesByNumber",
"XDPoS_getV2BlockByNumber",
"XDPoS_getMissedRoundsInEpochByBlockNum"
]
}
}GET /x402/v1/plugin-node/{address}/healthauth: B2B key + x402
For an oracle address: the known Plugin feeds it serves, its submissions in about the last 3 hours, rounds behind per feed, eligibility for the current round and its XDC gas balance.
| Parameter | Description |
|---|---|
address | Plugin oracle (node transmitter) address |
# 1) without payment: 402 with the payment requirements
curl -s "$BASE/x402/v1/plugin-node/0x987178C51721A2136B85f9c5cCa76AEb5A713030/health" -H "X-FeedPlumb-Key: $FEEDPLUMB_KEY"
# 2) with the x402 payment payload
curl -s "$BASE/x402/v1/plugin-node/0x987178C51721A2136B85f9c5cCa76AEb5A713030/health" -H "X-FeedPlumb-Key: $FEEDPLUMB_KEY" -H "X-PAYMENT: $PAYMENT"{
"address": "0x987178c51721a2136b85f9c5cca76aeb5a713030",
"addressXdc": "xdc987178c51721a2136b85f9c5cca76aeb5a713030",
"status": "healthy",
"reasons": [],
"feedsServed": 69,
"feedsShown": 50,
"gasBalanceXdc": "20.100667499701717149",
"lowGasThresholdXdc": "1",
"submissions": {
"windowBlocks": 5400,
"approxHours": 3,
"total": 145,
"lastSubmissionBlock": 108633542,
"lastSubmissionAgeS": 90,
"feedsActiveInWindow": 11,
"feedsIdleInWindow": 39
},
"feeds": [
{
"pair": "AAPL/USD",
"proxy": "0xd73aDd20E3905410B3817725CCabbE639B75B7Cc",
"aggregator": "0x40E8900E48ce19b85c3Eb01011CC69ae2ac0Dd71",
"latestRound": 733,
"submissionsInWindow": 0,
"allOracleSubmissionsInWindow": 0,
"feedActiveInWindow": false,
"missedWhileFeedActive": false,
"lastSubmittedRound": null,
"lastSubmissionBlock": null,
"roundsBehind": null,
"eligibleToSubmitNow": true
},
{
"pair": "ADA/USDT",
"proxy": "0x7bcC300260bd987f894cDc335c0A6C739b3277a6",
"aggregator": "0x3108A0eE7cf573FE534D09722AB77634Dd4C109C",
"latestRound": 31976,
"submissionsInWindow": 13,
"allOracleSubmissionsInWindow": 132,
"feedActiveInWindow": true,
"missedWhileFeedActive": false,
"lastSubmittedRound": 31976,
"lastSubmissionBlock": 108633435,
"roundsBehind": 0,
"eligibleToSubmitNow": true
}
],
"notCovered": [
"node web /health endpoint (operator-hosted; not probed)",
"PLI node-operator balances"
],
"source": {
"chainId": 50,
"block": 108633587,
"blockTime": 1792741235,
"blockTimeIso": "2026-10-23T07:40:35.000Z",
"methods": [
"getOracles()",
"latestRound()",
"oracleRoundState(address,uint32)",
"SubmissionReceived logs",
"eth_getBalance"
]
}
}GET /x402/health
Service health (free, no key).
curl -s $BASE/x402/healthGET /x402/openapi.json
This specification (free, no key).
curl -s $BASE/x402/openapi.jsonErrors
| Status | Meaning |
|---|---|
400 | invalid input (checked before payment) |
401 | missing or unknown API key |
402 | payment required, or the payment payload was refused (see error) |
403 | API key revoked, or B2B registration incomplete |
404 | unknown feed or pair (checked before payment) |
429 | per-key rate limit reached; see Retry-After |
502 | chain read failed; not settled and not billed |
Data and limits
- Feed verdicts never include the feed's answer value.
- The CGO response contains no gold price, valuation or price-feed data, and is not an attestation.
- Node health uses public chain data only; client version and fork readiness are not covered.
- Not financial advice.