/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.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| token | query, required | string | Binds 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
| Field | Type | Description | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| wallet required | object | wallet fields
| ||||||||||||||||||
| already_attested required | boolean | True when the wallet was already attested to this same account. |
401: Unauthorized
| Field | Type | Description |
|---|---|---|
| error required | string | Error code |
| message required | string | Human-readable message |
| retry_after | integer | Seconds to wait (only on 429) |
| retryAfter | integer | Seconds to wait for owner-scoped forecast-request quota errors. |
| limit_scope | string | Quota scope that rejected the request, such as standard or x_research. |
| quotaScope | string | Stable forecast-request quota scope, such as venue_market_daily. |
| limit | integer | Configured bound for the forecast-request quota that was exceeded. |
402: Payment Required
| Field | Type | Description |
|---|---|---|
| error required | string | Error code |
| message required | string | Human-readable message |
| retry_after | integer | Seconds to wait (only on 429) |
| retryAfter | integer | Seconds to wait for owner-scoped forecast-request quota errors. |
| limit_scope | string | Quota scope that rejected the request, such as standard or x_research. |
| quotaScope | string | Stable forecast-request quota scope, such as venue_market_daily. |
| limit | integer | Configured bound for the forecast-request quota that was exceeded. |
403: Insufficient credits for the requested route
| Field | Type | Description |
|---|---|---|
| error required | string | Error code |
| message required | string | Human-readable message |
| retry_after | integer | Seconds to wait (only on 429) |
| retryAfter | integer | Seconds to wait for owner-scoped forecast-request quota errors. |
| limit_scope | string | Quota scope that rejected the request, such as standard or x_research. |
| quotaScope | string | Stable forecast-request quota scope, such as venue_market_daily. |
| limit | integer | Configured bound for the forecast-request quota that was exceeded. |
404: Unknown link token (link_token_not_found). Not billed.
| Field | Type | Description |
|---|---|---|
| error required | string | Error code |
| message required | string | Human-readable message |
| retry_after | integer | Seconds to wait (only on 429) |
| retryAfter | integer | Seconds to wait for owner-scoped forecast-request quota errors. |
| limit_scope | string | Quota scope that rejected the request, such as standard or x_research. |
| quotaScope | string | Stable forecast-request quota scope, such as venue_market_daily. |
| limit | integer | Configured bound for the forecast-request quota that was exceeded. |
409: The paying wallet is attested to a different account (wallet_already_attested). Not billed.
| Field | Type | Description |
|---|---|---|
| error required | string | Error code |
| message required | string | Human-readable message |
| retry_after | integer | Seconds to wait (only on 429) |
| retryAfter | integer | Seconds to wait for owner-scoped forecast-request quota errors. |
| limit_scope | string | Quota scope that rejected the request, such as standard or x_research. |
| quotaScope | string | Stable forecast-request quota scope, such as venue_market_daily. |
| limit | integer | Configured 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.
| Field | Type | Description |
|---|---|---|
| error required | string | Error code |
| message required | string | Human-readable message |
| retry_after | integer | Seconds to wait (only on 429) |
| retryAfter | integer | Seconds to wait for owner-scoped forecast-request quota errors. |
| limit_scope | string | Quota scope that rejected the request, such as standard or x_research. |
| quotaScope | string | Stable forecast-request quota scope, such as venue_market_daily. |
| limit | integer | Configured 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.
| Field | Type | Description |
|---|---|---|
| error required | string | Error code |
| message required | string | Human-readable message |
| retry_after | integer | Seconds to wait (only on 429) |
| retryAfter | integer | Seconds to wait for owner-scoped forecast-request quota errors. |
| limit_scope | string | Quota scope that rejected the request, such as standard or x_research. |
| quotaScope | string | Stable forecast-request quota scope, such as venue_market_daily. |
| limit | integer | Configured 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 --request GET \
--header "x-quotient-api-key: $QUOTIENT_API_KEY" \
'https://quotient-api-gateway.onrender.com/api/v1/wallets/link?token=example'{
"wallet": {
"address": "0x52908400098527886e0f7030069857d2e4169ee7",
"chain_id": 8453,
"provider": null,
"method": "x402",
"attested_at": "2026-08-12T00:00:00Z"
},
"already_attested": false
}