Skip to Content

POST /api/v1/auth/verify

Verify a SIWE signature and create an authenticated session. Returns a JWT token and user object. Supports both EOA signatures and smart wallet signatures (ERC-1271, ERC-6492).

Authentication: None

Cache: None

Request Body

FieldTypeRequiredDescription
messagestringYesThe full SIWE message string
signaturestringYesHex-encoded signature (0x...)

Sample Request

curl -X POST https://api.grails.app/api/v1/auth/verify \ -H "Content-Type: application/json" \ -d '{ "message": "api.grails.app wants you to sign in with your Ethereum account:\n0x1234...5678\n\nSign in to Grails\n\nURI: https://api.grails.app\nVersion: 1\nChain ID: 1\nNonce: a1b2c3d4e5f6a7b8\nIssued At: 2026-04-07T12:00:00.000Z", "signature": "0xabc123..." }'

Response

// 200 OK { "success": true, "data": { "token": "eyJhbGciOiJIUzI1NiIs...", "user": { "id": 1, "address": "0x1234567890abcdef1234567890abcdef12345678", "email": null, "emailVerified": false, "telegram": null, "discord": null, "notifyOnOfferReceived": true, "notifyOnListingSold": true, "minOfferThreshold": null, "createdAt": "2026-01-15T00:00:00.000Z", "lastSignIn": "2026-04-07T12:00:00.000Z" } }, "meta": { "timestamp": "2026-04-07T12:00:00.000Z", "version": "1.0.0" } }

Error Responses

StatusCodeDescription
400VALIDATION_ERRORInvalid request body
400INVALID_MESSAGESIWE message missing required fields
401INVALID_SIWE_MESSAGECannot parse SIWE message format
401INVALID_NONCENonce not found or already used
401NONCE_EXPIREDNonce has expired (5-minute window)
401SIGNATURE_VERIFICATION_FAILEDSignature does not match message signer
401INVALID_SIGNATUREFailed to verify signature
500INTERNAL_ERRORServer error during verification
Last updated on