POST /api/auth/verify

Verify a signed nonce and receive a JWT. The nonce is consumed atomically -- it cannot be reused.

Request

POST /api/auth/verify
Content-Type: application/json

Authentication: None

Body

Field
Type
Required
Description

wallet

string

Yes

Solana wallet address (base58)

nonce

string

Yes

signature

string

Yes

Base58-encoded ed25519 detached signature

The signature must be over the message: Sign this message to authenticate: <nonce>

Example

curl -X POST https://api-blowfish.neuko.ai/api/auth/verify \
  -H "Content-Type: application/json" \
  -d '{
    "wallet": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
    "nonce": "nonce-from-challenge",
    "signature": "base58-encoded-ed25519-signature"
  }'

TypeScript example

Response

200 OK

JWT payload:

Claim
Value

sub

Wallet address

scope

["read", "trade"]

iat

Issued-at timestamp

exp

Expiry timestamp (15 minutes from issue)

Errors

Status
Error
Cause

400

wallet is required

Missing wallet field

400

signature is required

Missing signature field

400

nonce is required

Missing nonce field

400

Invalid wallet address format

Address fails PublicKey validation

401

Invalid or expired nonce

Nonce not found, already used, or expired

401

Invalid signature

ed25519 verification failed

500

Server configuration error

JWT secret not configured

500

Internal server error

Unexpected server error

Notes

  • Nonces are single-use. Once verified (or expired), a new challenge is required.

  • The JWT expires in 15 minutes. Re-authenticate when you receive a 401 on subsequent requests.

  • Use the JWT as Authorization: Bearer <token> on all authenticated endpoints.

Last updated