Authentication
Authentication (SIWE)
Authenticate using Sign-In with Ethereum (SIWE). This exchanges a wallet signature for a secure session cookie used in write endpoints (images, metadata, projects, comments).
Endpoints
GET
/api/auth/nonce?address={wallet_address}
Generates a one-time nonce for the given wallet address. Must be called before signing.
Response
{ "nonce": "a1b2c3d4e5f6" }POST
/api/auth/verify
Verifies the signed SIWE message. Returns a Set-Cookie header with your session.
Request Body
Response
{
"message": "the prepared SIWE message string",
"signature": "0x..."
}Response
Response
{ "ok": true, "address": "0x..." }200 OK422 Invalid nonce or signature
Node.js Example
Example Code
import { ethers } from "ethers";
import { SiweMessage } from "siwe";
const BASE_URL = "https://launchonbasis.com";
async function authenticate() {
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY);
const address = await wallet.getAddress();
// 1. Get nonce
const nonceRes = await fetch(`${BASE_URL}/api/auth/nonce?address=${address}`);
const { nonce } = await nonceRes.json();
// 2. Create & sign SIWE message
const message = new SiweMessage({
domain: "launchonbasis.com",
address,
statement: "Sign in to Basis API.",
uri: BASE_URL,
version: "1",
chainId: 56,
nonce,
});
const preparedMessage = message.prepareMessage();
const signature = await wallet.signMessage(preparedMessage);
// 3. Verify — returns session cookie
const verifyRes = await fetch(`${BASE_URL}/api/auth/verify`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ message: preparedMessage, signature }),
});
// Extract the session cookie for subsequent requests
const sessionCookie = verifyRes.headers.get("set-cookie");
return sessionCookie;
}Python Example
Example Code
import requests
from eth_account import Account
from eth_account.messages import encode_defunct
from datetime import datetime
import os
BASE_URL = "https://launchonbasis.com"
private_key = os.environ["PRIVATE_KEY"]
account = Account.from_key(private_key)
address = account.address
# 1. Get nonce
nonce = requests.get(f"{BASE_URL}/api/auth/nonce?address={address}").json()["nonce"]
# 2. Construct & sign SIWE message
issued_at = datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S.%fZ")
message = (
f"launchonbasis.com wants you to sign in with your Ethereum account:\n"
f"{address}\n\nSign in to Basis API.\n\n"
f"URI: {BASE_URL}\nVersion: 1\nChain ID: 56\n"
f"Nonce: {nonce}\nIssued At: {issued_at}"
)
signature = Account.sign_message(
encode_defunct(text=message), private_key=private_key
).signature.hex()
# 3. Verify — session object stores the cookie automatically
session = requests.Session()
session.post(f"{BASE_URL}/api/auth/verify", json={"message": message, "signature": signature})
# Use 'session' for all subsequent requests