POST /v1/auth/wallet/challenge
https://api.triport.io/v1/auth/wallet/challengeStart a wallet sign-in by requesting a single-use nonce and a human-readable message for the wallet to sign.
This is the first of the two-step wallet authentication flow. You send the
wallet address and its chain, and Triport returns a freshly minted nonce
(a UUID) together with a message string. The wallet extension (e.g. a browser
wallet) displays the message verbatim so the user can see exactly what
they are about to sign; the user then signs it and you submit the signature to
POST /v1/auth/wallet/verify to complete sign-in.
The nonce is single-use and expires 5 minutes after it is issued. If the
nonce expires before you call the verify endpoint, request a new challenge.
This endpoint does not authenticate the caller and does not set any cookies —
the session is only established on a successful wallet/verify call. Pass the
message to the wallet unchanged: any modification will cause the recovered
signature to mismatch on verify.
Parameters
Request body (JSON):
addressstringrequiredevm: 0x-prefixed, exactly 40 hex characters (42 chars total). For solana: a base58-encoded 32-byte public key.chainstringrequired"evm" or "solana".Response
200 OK
noncestringwallet/verify.messagestringErrors
| Code | HTTP | When it happens |
|---|---|---|
invalid_json | 400 | The request body is not valid JSON, or exceeds the 4 KB limit. |
invalid_address | 400 | chain is not evm/solana, or address fails the format check for that chain. |
method_not_allowed | 405 | A method other than POST was used. |
internal | 500 | The challenge could not be persisted server-side. |
Errors share the standard error envelope — see errors.md.
Examples
JavaScript (fetch)
const res = await fetch('https://api.triport.io/v1/auth/wallet/challenge', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
address: '0x52908400098527886E0F7030069857D2E4169EE7',
chain: 'evm',
}),
});
const { nonce, message } = await res.json();
// Hand `message` to the wallet, then call wallet/verify with the signature.TypeScript SDK (@triport/sdk)
import { TriportClient } from '@triport/sdk';
const client = new TriportClient();
const { nonce, message } = await client.auth.wallet.challenge({
address: '0x52908400098527886E0F7030069857D2E4169EE7',
chain: 'evm',
});Python (triport-sdk)
from triport import TriportClient
client = TriportClient()
challenge = client.auth.wallet.challenge(
address="0x52908400098527886E0F7030069857D2E4169EE7",
chain="evm",
)
nonce, message = challenge["nonce"], challenge["message"]Notes
- Two-step flow: always follow this call with
POST /v1/auth/wallet/verify, passing back the samenonce,address,chain, and the wallet'ssignature. The verify step burns the nonce and issues the session cookies. - 5-minute TTL: request a new challenge if the user takes too long to sign.
- Solana example: for
chain: "solana",addressis a base58 32-byte pubkey (e.g.9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM); the returnedmessageis signed with the wallet's ed25519 key. - See the console authentication overview for how this flow fits alongside email OTP and Google OAuth sign-in.