Moonbase Docs
Guides

Authentication

How to authenticate REST API requests with API keys

Overview

Moonbase REST API uses API key authentication. All authenticated endpoints require two headers:

  • NOVA-KEY - Your API key
  • NOVA-SECRET - Your API secret

Getting API Keys

API keys can be created through the Moonbase dashboard. Each key has:

  • API Key: Public identifier for your key
  • API Secret: Private secret for authentication (shown only once at creation)

Store your API secret securely. It cannot be recovered if lost.

Authentication Headers

HeaderDescription
NOVA-KEYYour API key
NOVA-SECRETYour API secret

Example Requests

GET Request

const apiKey = 'your_api_key';
const apiSecret = 'your_api_secret';

const response = await fetch('https://api.dev.mbhq.net/api/v1/orders/active', {
  method: 'GET',
  headers: {
    'NOVA-KEY': apiKey,
    'NOVA-SECRET': apiSecret
  }
});

POST Request

const apiKey = 'your_api_key';
const apiSecret = 'your_api_secret';

const response = await fetch('https://api.dev.mbhq.net/api/v1/orders', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'NOVA-KEY': apiKey,
    'NOVA-SECRET': apiSecret
  },
  body: JSON.stringify({
    product: 'BTC-VND',
    side: 'BUY',
    type: 'LIMIT',
    base_size: '0.001',
    limit_price: '2500000000'
  })
});

DELETE Request

const apiKey = 'your_api_key';
const apiSecret = 'your_api_secret';

const response = await fetch('https://api.dev.mbhq.net/api/v1/order/active?order_id=123', {
  method: 'DELETE',
  headers: {
    'Content-Type': 'application/json',
    'NOVA-KEY': apiKey,
    'NOVA-SECRET': apiSecret
  }
});

Complete Client Example

class MoonbaseClient {
  private apiKey: string;
  private apiSecret: string;
  private baseUrl: string;

  constructor(apiKey: string, apiSecret: string, baseUrl = 'https://api.dev.mbhq.net') {
    this.apiKey = apiKey;
    this.apiSecret = apiSecret;
    this.baseUrl = baseUrl;
  }

  private getHeaders(includeContentType = false): Record<string, string> {
    const headers: Record<string, string> = {
      'NOVA-KEY': this.apiKey,
      'NOVA-SECRET': this.apiSecret
    };
    if (includeContentType) {
      headers['Content-Type'] = 'application/json';
    }
    return headers;
  }

  async request(method: string, path: string, body?: object): Promise<any> {
    const response = await fetch(`${this.baseUrl}${path}`, {
      method,
      headers: this.getHeaders(!!body),
      body: body ? JSON.stringify(body) : undefined
    });
    return response.json();
  }

  // Convenience methods
  async getActiveOrders(product?: string) {
    const path = product ? `/api/v1/orders/active?product=${product}` : '/api/v1/orders/active';
    return this.request('GET', path);
  }

  async createOrder(order: {
    product: string;
    side: 'BUY' | 'SELL';
    type: 'LIMIT' | 'MARKET';
    base_size: string;
    limit_price?: string;
  }) {
    return this.request('POST', '/api/v1/orders', order);
  }

  async cancelOrder(orderId: string) {
    return this.request('DELETE', `/api/v1/order/active?order_id=${orderId}`);
  }

  async cancelAllOrders() {
    return this.request('DELETE', '/api/v1/orders/active/all');
  }

  async getAccount(userId: string) {
    return this.request('GET', `/accounts/${userId}`);
  }
}

// Usage
const client = new MoonbaseClient('your_api_key', 'your_api_secret');

// Get active orders
const orders = await client.getActiveOrders('BTC-VND');

// Create a limit order
const order = await client.createOrder({
  product: 'BTC-VND',
  side: 'BUY',
  type: 'LIMIT',
  base_size: '0.001',
  limit_price: '2500000000'
});

Go Example

package main

import (
    "bytes"
    "encoding/json"
    "net/http"
)

type MoonbaseClient struct {
    baseURL   string
    apiKey    string
    apiSecret string
}

func (c *MoonbaseClient) request(method, path string, body interface{}) (*http.Response, error) {
    var bodyReader *bytes.Reader
    if body != nil {
        jsonBody, _ := json.Marshal(body)
        bodyReader = bytes.NewReader(jsonBody)
    }

    req, err := http.NewRequest(method, c.baseURL+path, bodyReader)
    if err != nil {
        return nil, err
    }

    req.Header.Set("NOVA-KEY", c.apiKey)
    req.Header.Set("NOVA-SECRET", c.apiSecret)
    if body != nil {
        req.Header.Set("Content-Type", "application/json")
    }

    return http.DefaultClient.Do(req)
}

API Endpoints

EnvironmentBase URL
Developmenthttps://api.dev.mbhq.net
Productionhttps://api.mbhq.net

Error Responses

401 Unauthenticated

{
  "error": {
    "code": "AUTH_REQUIRED",
    "message": "this request requires user authentication"
  }
}

Common causes:

  • Missing NOVA-KEY or NOVA-SECRET headers
  • Invalid API key or secret
  • API key expired or revoked

403 Permission Denied

{
  "error": {
    "code": "INSUFFICIENT_SCOPE",
    "message": "this request requires additional scope"
  }
}

Public Endpoints

Some endpoints don't require authentication:

  • GET /products - List products
  • GET /products/{id}/orderbook - Get orderbook
  • GET /products/{id}/trades - Get recent trades
  • GET /assets - List assets

Best Practices

  1. Secure storage: Store API secrets in environment variables or secure vaults
  2. Never expose: Don't expose secrets in client-side code or logs
  3. Key rotation: Rotate API keys periodically
  4. Separate keys: Use different keys for different environments
  5. Read-only keys: Use read-only keys for applications that only need to read data

Next Steps