> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trustgated.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Trust Oracle

> Authoritative wallet and token reads through the TrustGate proxy. 0.001 USDC per query, settled with x402.

## When to use this

Use the oracle when you need an authoritative wallet read, or the same ERC-20 score Token Shield uses, and you are willing to settle a micropayment. The widget and batch paths are free and thinner. This is the paid, hardened path.

Do not send contract addresses to the wallet oracle. It returns `CONTRACT_NOT_WALLET` and tells you to use Token Shield.

## Endpoints

Integrator-facing proxy (recommended):

```text theme={null}
GET  https://www.trustgated.xyz/api/oracle/{wallet}
GET  https://www.trustgated.xyz/api/oracle/token/{address}
POST https://www.trustgated.xyz/api/oracle/{…}   (body forwarded)
```

Open CORS. Forwarded payment headers: `X-Payment`, `X-Payment-Required`, `X-Payment-Tx`.

There is also an upstream host configured as `ORACLE_URL` / `NEXT_PUBLIC_ORACLE_URL`. Browser clients should not call it. The proxy exists so they never hold those credentials.

## Payment: x402

Paid endpoints use the [x402 payment standard](https://www.x402.org).

<Steps>
  <Step title="Challenge">
    Send the GET with no payment header.

    ```
    GET /api/oracle/0x60C05e2d820CE989E944ED4e7bb33bAEB8705c62
    → 402 Payment Required
    ```

    Body names the recipient, amount (`0.001`), currency (`USDC`), network (`arc-testnet`), and memo.
  </Step>

  <Step title="Settle">
    Transfer 0.001 USDC (6 decimals) on Arc Testnet to the stated recipient. USDC token: `0x3600000000000000000000000000000000000000`.
  </Step>

  <Step title="Replay">
    Repeat the same GET with:

    ```
    X-Payment: <base64 JSON { txHash, nonce, from, network: "Arc Testnet", chainId: 5042002, amount: "0.001", currency: "USDC", recipient }>
    X-Payment-Tx: <txHash>
    ```

    Successful payment replays return `200` with the score body. Rejected proofs return `422`.
  </Step>
</Steps>

## Wallet response (200)

The proxy re-scores a successful upstream body, strips any raw `breakdown`, and adds TrustGate fields:

```json theme={null}
{
  "address": "0x60C05e2d820CE989E944ED4e7bb33bAEB8705c62",
  "score": 57,
  "tier": "MEDIUM",
  "recommendation": "TIME_LOCKED",
  "confidence": 70,
  "flags": [],
  "summary": "Ordinary history. Nothing alarming, nothing exceptional.",
  "publicExplain": {
    "headline": "MEDIUM trust",
    "lines": []
  },
  "protocolExplain": {
    "categories": []
  },
  "scoreStability": "stable",
  "directionDrivers": [],
  "snapshotId": "snap_…",
  "scoringVersion": "v1.0",
  "queriedAt": "2026-08-15T10:42:13.094Z",
  "network": "arc-testnet",
  "source": "Arc Onchain Activity"
}
```

`recommendation` is how TrustGate's own payment rails would route this score. It is not an instruction to your protocol.

| `recommendation`   | Meaning                                              |
| ------------------ | ---------------------------------------------------- |
| `BLOCKED`          | Score 0. Do not settle.                              |
| `TIME_LOCKED`      | Score below 60. 24h hold path.                       |
| `INSTANT`          | Score 60–79. Instant HIGH band.                      |
| `INSTANT_PRIORITY` | Score 80+. Same onchain HIGH band; UI-only priority. |

`tier` is one of `BLOCKED | LOW | MEDIUM | HIGH | HIGH_ELITE`.

`publicExplain.tone` is `positive | neutral | caution | danger`. NFT/contract branches on `/api/oracle/token/{address}` return `confidence` as `HIGH|MEDIUM|LOW` (string), not a number.

## TypeScript sketch

```ts theme={null}
async function getTrust(address: string) {
  const url = `https://www.trustgated.xyz/api/oracle/${address}`;
  const challenge = await fetch(url);
  if (challenge.status === 200) return challenge.json();
  if (challenge.status !== 402) {
    throw new Error(`Oracle error ${challenge.status}`);
  }
  const requirement = await challenge.json();
  const txHash = await sendUsdc({
    to: requirement.recipient,
    amount: requirement.amount,
  });
  const paid = await fetch(url, {
    headers: {
      "X-Payment": Buffer.from(
        JSON.stringify({
          txHash,
          nonce: crypto.randomUUID(),
          from: payer,
          network: "Arc Testnet",
          chainId: 5042002,
          amount: requirement.amount,
          currency: "USDC",
          recipient: requirement.recipient,
        })
      ).toString("base64"),
      "X-Payment-Tx": txHash,
    },
  });
  return paid.json();
}
```

## Token oracle

`GET /api/oracle/token/{address}` is the Token Shield path. Official issuers short-circuit to VERIFIED. NFTs and non-token contracts are scored locally (free). ERC-20s go upstream and require x402 the same way.

For a compact, free ERC-20 badge payload use `/api/widget/score/{address}` instead. TrustGate pays that hop.

## Errors

| Status | Meaning                                                             |
| ------ | ------------------------------------------------------------------- |
| `400`  | Invalid address, or `CONTRACT_NOT_WALLET`                           |
| `402`  | Payment required. Body is the requirement.                          |
| `422`  | Payment proof rejected (wrong amount, recipient, or replayed nonce) |
| `502`  | Upstream RPC / oracle failure. Retry once after backoff.            |

## Related

<CardGroup cols={2}>
  <Card title="Wallet Trust Score" icon="wallet" href="/products/wallet-trust-score">
    What the read means.
  </Card>

  <Card title="API reference" icon="brackets-curly" href="/integrate/api-reference">
    Every oracle-adjacent path.
  </Card>
</CardGroup>
