GET

/api/v1/wallets/link

Attest the paying wallet to a Quotient account via x402

Payment-as-proof wallet attestation. First obtain a single-use link token from POST /api/auth/wallets/x402-token (authenticated with x-quotient-api-key or a Privy bearer), then call this route with an x402 payment from the wallet being linked — a Bankr wallet via `bankr x402 call`, or any x402-capable signer. The gateway verifies the payment signature and the settled payer wallet is attested to the token's account. Wallets whose keys cannot be exported (custodial or provider-managed) can therefore be linked without any message-signing support. A wallet already attested to a different account returns a non-billable 409; the signature-challenge alternative lives at POST /api/auth/wallets/challenge + /attest.

Price $0.01Auth x-quotient-api-key or x402Limit 1/s · 5/min · 20/day

Parameters

NameInTypeDescription
tokenquery, requiredstringBinds this payment's payer wallet to the Quotient account the token was issued to. Expires after 15 minutes and is consumed on first use.

Pattern: ^qlt_[A-Za-z0-9_-]{43}$

Responses

200: The paying wallet is now attested to the token's account
FieldTypeDescription
wallet
required
object
wallet fields
FieldTypeDescription
address
required
stringLowercased attested wallet address.
chain_id
required
integer
provider
required
string | null
method
required
"eoa" | "erc1271" | "erc6492" | "x402"How control was proven; x402 means a settled payment signature.
attested_at
required
string
already_attested
required
booleanTrue when the wallet was already attested to this same account.
401: Unauthorized
FieldTypeDescription
error
required
stringError code
message
required
stringHuman-readable message
retry_afterintegerSeconds to wait (only on 429)
retryAfterintegerSeconds to wait for owner-scoped forecast-request quota errors.
limit_scopestringQuota scope that rejected the request, such as standard or x_research.
quotaScopestringStable forecast-request quota scope, such as venue_market_daily.
limitintegerConfigured bound for the forecast-request quota that was exceeded.
402: Payment Required
FieldTypeDescription
error
required
stringError code
message
required
stringHuman-readable message
retry_afterintegerSeconds to wait (only on 429)
retryAfterintegerSeconds to wait for owner-scoped forecast-request quota errors.
limit_scopestringQuota scope that rejected the request, such as standard or x_research.
quotaScopestringStable forecast-request quota scope, such as venue_market_daily.
limitintegerConfigured bound for the forecast-request quota that was exceeded.
403: Insufficient credits for the requested route
FieldTypeDescription
error
required
stringError code
message
required
stringHuman-readable message
retry_afterintegerSeconds to wait (only on 429)
retryAfterintegerSeconds to wait for owner-scoped forecast-request quota errors.
limit_scopestringQuota scope that rejected the request, such as standard or x_research.
quotaScopestringStable forecast-request quota scope, such as venue_market_daily.
limitintegerConfigured bound for the forecast-request quota that was exceeded.
404: Unknown link token (link_token_not_found). Not billed.
FieldTypeDescription
error
required
stringError code
message
required
stringHuman-readable message
retry_afterintegerSeconds to wait (only on 429)
retryAfterintegerSeconds to wait for owner-scoped forecast-request quota errors.
limit_scopestringQuota scope that rejected the request, such as standard or x_research.
quotaScopestringStable forecast-request quota scope, such as venue_market_daily.
limitintegerConfigured bound for the forecast-request quota that was exceeded.
409: The paying wallet is attested to a different account (wallet_already_attested). Not billed.
FieldTypeDescription
error
required
stringError code
message
required
stringHuman-readable message
retry_afterintegerSeconds to wait (only on 429)
retryAfterintegerSeconds to wait for owner-scoped forecast-request quota errors.
limit_scopestringQuota scope that rejected the request, such as standard or x_research.
quotaScopestringStable forecast-request quota scope, such as venue_market_daily.
limitintegerConfigured bound for the forecast-request quota that was exceeded.
422: Missing/expired token, or the call carried no verifiable x402 payer (x402_payment_required). Not billed.
FieldTypeDescription
error
required
stringError code
message
required
stringHuman-readable message
retry_afterintegerSeconds to wait (only on 429)
retryAfterintegerSeconds to wait for owner-scoped forecast-request quota errors.
limit_scopestringQuota scope that rejected the request, such as standard or x_research.
quotaScopestringStable forecast-request quota scope, such as venue_market_daily.
limitintegerConfigured bound for the forecast-request quota that was exceeded.
429: The caller exceeded a per-second, per-minute, daily, or concurrency limit. No credits are debited and no x402 payment is settled for this response.
FieldTypeDescription
error
required
stringError code
message
required
stringHuman-readable message
retry_afterintegerSeconds to wait (only on 429)
retryAfterintegerSeconds to wait for owner-scoped forecast-request quota errors.
limit_scopestringQuota scope that rejected the request, such as standard or x_research.
quotaScopestringStable forecast-request quota scope, such as venue_market_daily.
limitintegerConfigured bound for the forecast-request quota that was exceeded.

Set QUOTIENT_API_KEY in your shell and replace example identifiers with returned IDs before running a request.

curl
curl --request GET \
  --header "x-quotient-api-key: $QUOTIENT_API_KEY" \
  'https://quotient-api-gateway.onrender.com/api/v1/wallets/link?token=example'
200 · application/json
{
  "wallet": {
    "address": "0x52908400098527886e0f7030069857d2e4169ee7",
    "chain_id": 8453,
    "provider": null,
    "method": "x402",
    "attested_at": "2026-08-12T00:00:00Z"
  },
  "already_attested": false
}