Skip to main content

Documentation Index

Fetch the complete documentation index at: https://nexus.gerowallet.io/docs/llms.txt

Use this file to discover all available pages before exploring further.

Gero Nexus uses JWT (JSON Web Token) authentication. All API requests must include a valid access token in the Authorization header.

Authentication Methods

Gero Nexus supports two authentication methods depending on your use case:

User Authentication

For web applications
  • Requires email and password
  • Full account features
  • Linked to user account

Device Authentication

For mobile apps
  • No credentials required
  • Device-based tokens
  • Auto-registration

Quick Start

1. Get Your Access Token

curl -X POST "https://nexus-dev.gerowallet.io/api/auth/login" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "your-email@example.com",
    "password": "your-password"
  }'
Response:
{
  "accessToken": "eyJhbGciOiJIUzUxMiJ9...",
  "refreshToken": "eyJhbGciOiJIUzUxMiJ9...",
  "tokenType": "Bearer",
  "expiresIn": 3600000,
  "user": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "email": "your-email@example.com",
    "roles": ["USER"]
  }
}

2. Use the Token

Include the access token in the Authorization header for all API requests:
curl -X GET "https://nexus-dev.gerowallet.io/api/blocks/latest" \
  -H "Authorization: Bearer eyJhbGciOiJIUzUxMiJ9..."

User Authentication

For web applications and services that require user accounts.

Register a New Account

curl -X POST "https://nexus-dev.gerowallet.io/api/auth/register" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "securePassword123",
    "username": "myusername"
  }'

Login

curl -X POST "https://nexus-dev.gerowallet.io/api/auth/login" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "securePassword123"
  }'

Logout

Invalidates the current session and refresh token:
curl -X POST "https://nexus-dev.gerowallet.io/api/auth/logout" \
  -H "Authorization: Bearer your-access-token"

Device Authentication

For mobile applications that don’t require user credentials. Devices are automatically registered on first use.

Authenticate Device

curl -X POST "https://nexus-dev.gerowallet.io/api/auth/device" \
  -H "Content-Type: application/json" \
  -d '{
    "deviceId": "550e8400-e29b-41d4-a716-446655440000",
    "deviceName": "iPhone 15 Pro",
    "platform": "IOS"
  }'

Platform Values

PlatformDescription
IOSiOS devices (iPhone, iPad)
ANDROIDAndroid devices
WEBWeb browsers

Token Management

Token Structure

When you authenticate, you receive:
FieldDescription
accessTokenShort-lived token for API requests (1 hour)
refreshTokenLong-lived token to get new access tokens (7 days)
tokenTypeAlways Bearer
expiresInAccess token lifetime in milliseconds

Refresh Tokens

Before your access token expires, use the refresh token to get a new one:
curl -X POST "https://nexus-dev.gerowallet.io/api/auth/refresh" \
  -H "Content-Type: application/json" \
  -d '{
    "refreshToken": "your-refresh-token"
  }'
Refresh tokens are single-use. Each refresh returns a new refresh token.

Making Authenticated Requests

Include the access token in the Authorization header:
curl -X GET "https://nexus-dev.gerowallet.io/api/blocks/latest" \
  -H "Authorization: Bearer eyJhbGciOiJIUzUxMiJ9..."

Example: Secure API Client

Here’s a production-ready example with automatic token refresh:
class GeroNexusClient {
  constructor() {
    this.baseUrl = 'https://nexus-dev.gerowallet.io';
    this.accessToken = null;
    this.refreshToken = null;
    this.tokenExpiry = null;
  }

  async authenticate(email, password) {
    const response = await fetch(`${this.baseUrl}/api/auth/login`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email, password })
    });

    const data = await response.json();
    this.setTokens(data);
    return data;
  }

  async authenticateDevice(deviceId, deviceName, platform) {
    const response = await fetch(`${this.baseUrl}/api/auth/device`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ deviceId, deviceName, platform })
    });

    const data = await response.json();
    this.setTokens(data);
    return data;
  }

  setTokens(data) {
    this.accessToken = data.accessToken;
    this.refreshToken = data.refreshToken;
    this.tokenExpiry = Date.now() + data.expiresIn - 60000; // 1 min buffer
  }

  async ensureValidToken() {
    if (!this.tokenExpiry || Date.now() >= this.tokenExpiry) {
      await this.refreshAccessToken();
    }
  }

  async refreshAccessToken() {
    const response = await fetch(`${this.baseUrl}/api/auth/refresh`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ refreshToken: this.refreshToken })
    });

    const data = await response.json();
    this.setTokens(data);
  }

  async request(endpoint, options = {}) {
    await this.ensureValidToken();

    const response = await fetch(`${this.baseUrl}${endpoint}`, {
      ...options,
      headers: {
        'Authorization': `Bearer ${this.accessToken}`,
        'Content-Type': 'application/json',
        ...options.headers
      }
    });

    if (!response.ok) {
      throw new Error(`API error: ${response.status}`);
    }

    return response.json();
  }

  // Convenience methods
  getLatestBlock() {
    return this.request('/api/blocks/latest');
  }

  getTransaction(hash) {
    return this.request(`/v1/transactions/${hash}`);
  }
}

// Usage
const client = new GeroNexusClient();
await client.authenticate('user@example.com', 'password');
const block = await client.getLatestBlock();

Error Handling

Common Authentication Errors

401 Unauthorized
error
Invalid or expired token
{
  "error": "Unauthorized",
  "message": "Invalid or expired access token"
}
Solution: Refresh your access token or re-authenticate.
401 Invalid Credentials
error
Wrong email or password
{
  "error": "Invalid email or password"
}
Solution: Check your credentials and try again.
403 Forbidden
error
Insufficient permissions
{
  "error": "Forbidden",
  "message": "You don't have permission to access this resource"
}
Solution: Check if your account has the required role/permissions.

Best Practices

Web Applications:
  • Store tokens in httpOnly cookies when possible
  • Use localStorage only if cookies aren’t an option
  • Never store tokens in sessionStorage for persistent auth
Mobile Applications:
  • Use iOS Keychain or Android Keystore
  • Never store tokens in plain text
  • Clear tokens on logout and app uninstall
Server Applications:
  • Store tokens in secure environment variables
  • Use secret management services (AWS Secrets Manager, HashiCorp Vault)
  • Never log tokens
  • Refresh tokens proactively before expiry (60 seconds buffer)
  • Implement retry logic for failed refreshes
  • Handle refresh token expiry by re-authenticating
  • Queue requests while refreshing to avoid race conditions
iOS:
let deviceId = UIDevice.current.identifierForVendor?.uuidString
Android:
val deviceId = Settings.Secure.getString(
    context.contentResolver,
    Settings.Secure.ANDROID_ID
)
Web:
// Generate once and store
const deviceId = localStorage.getItem('deviceId')
  || (localStorage.setItem('deviceId', crypto.randomUUID()),
      localStorage.getItem('deviceId'));
Handle token errors gracefully:
  1. 401 with valid refresh token → Refresh and retry
  2. 401 with expired refresh token → Re-authenticate
  3. Network error → Retry with exponential backoff
  4. 403 → Check user permissions, may need different credentials

Next Steps

Quick Start

Make your first authenticated API call

Rate Limits

Understand rate limiting and quotas

Error Handling

Learn how to handle API errors

API Reference

Explore all available endpoints

Security Question? Contact our security team at security@gerowallet.io