Back to Blog

Developer / C07

Аутентификация MERX API: ключи, разрешения и лимиты запросов

Every API integration starts with authentication. Get it right, and your automated energy trading runs smoothly around the clock. Get it wrong, and you are dealing with leaked credentials, unexplained 403 errors, or rate limit bans that halt your production systems at the worst possible moment.

MERX provides two authentication methods, each designed for a different use case. This article covers both in detail - how they work, when to use each, how to manage permissions granularly, and what rate limits apply across the API surface.

Два метода аутентификации

MERX supports two ways to authenticate API requests: API keys and JWT tokens. They serve different purposes and are not interchangeable.

API Key Authentication

API keys are long-lived credentials designed for server-to-server communication. You create them through the API or admin panel, assign specific permissions, and include them in every request via the X-API-Key header.

curl https://merx.exchange/api/v1/prices \
  -H "X-API-Key: merx_live_k7x9m2p4..."

API keys are the right choice when:

API keys never expire on their own. They remain valid until you explicitly revoke them. This makes them convenient for long-running services but demands careful management.

JWT Token Authentication

JWT tokens are short-lived credentials issued after a login. You authenticate with your email and password (or via OAuth), receive a JWT, and include it in requests via the Authorization header with a Bearer prefix.

curl https://merx.exchange/api/v1/balance \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

JWTs are the right choice when:

JWT tokens issued by MERX expire after 24 hours. After expiration, the client must re-authenticate to get a new token. Refresh tokens extend sessions without requiring the user to log in again.

Which One to Use

For programmatic integrations - payment bots, automated trading, backend services - use API keys. They are simpler to manage, support granular permissions, and do not require a login flow.

For user-facing applications where a human logs in, use JWT tokens. They provide session-based access with automatic expiration, reducing the risk of credential leakage from client-side code.

You can use both in the same system. A common pattern: JWT authentication for your admin panel (human operators log in to manage settings), API key authentication for your backend services (automated order creation, balance monitoring).

Создание и управление API-ключами

Creating a Key

Create API keys via the API itself or through the MERX web dashboard. The API endpoint is POST /api/v1/keys:

curl -X POST https://merx.exchange/api/v1/keys \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "production-order-bot",
    "permissions": ["create_orders", "view_orders", "view_balance"]
  }'

The response includes the full API key. This is the only time the complete key is returned. Store it immediately in your secrets manager.

{
  "id": "key_8f3k2m9x",
  "name": "production-order-bot",
  "key": "merx_live_k7x9m2p4q8r1s5t3u7v2w6x0y4z...",
  "permissions": ["create_orders", "view_orders", "view_balance"],
  "created_at": "2026-03-30T10:00:00Z"
}

Note: the key creation endpoint requires JWT authentication. You must log in first to create API keys. This is a deliberate security decision - API keys cannot create other API keys.

Using the JavaScript SDK

import { MerxClient } from 'merx-sdk';

const merx = new MerxClient({
  apiKey: process.env.MERX_API_KEY,
  baseUrl: 'https://merx.exchange/api/v1',
});

// The SDK automatically includes the X-API-Key header
const prices = await merx.prices.list();
const balance = await merx.account.getBalance();

Using the Python SDK

from merx_sdk import MerxClient

client = MerxClient(
    api_key="merx_live_k7x9m2p4...",
    base_url="https://merx.exchange/api/v1",
)

prices = client.get_prices()
balance = client.get_balance()

Listing and Revoking Keys

List all active keys for your account:

curl https://merx.exchange/api/v1/keys \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

Revoke a key immediately:

curl -X DELETE https://merx.exchange/api/v1/keys/key_8f3k2m9x \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

Revocation is instant. Any request using the revoked key returns 401 immediately. There is no grace period.

Типы разрешений

MERX API keys support granular permissions. When creating a key, you specify exactly which operations it can perform. A key without a required permission receives a 403 Forbidden response.

Available Permissions

PermissionDescriptionTypical Use Case
view_balanceRead account balance and transaction historyMonitoring dashboards, alerting
view_ordersRead order status and order historyOrder tracking, reporting
create_ordersCreate new energy and bandwidth ordersAutomated trading bots
broadcastSubmit signed transactions for broadcastCustom transaction workflows

Permission Design Principles

Least privilege. Give each key only the permissions it needs. A monitoring dashboard does not need create_orders. A price display widget does not need view_balance.

Separate keys for separate concerns. Use one key for your order bot (create_orders, view_orders, view_balance) and a different key for your monitoring system (view_balance, view_orders). If the monitoring key leaks, the attacker cannot create orders.

No withdrawal permission on API keys. Withdrawals require JWT authentication. This is intentional. An API key, even with full permissions, cannot withdraw funds from your account. This adds a layer of protection for the highest-risk operation.

Example: Minimal Key for a Price Widget

A public-facing price widget only needs to fetch prices. It does not need authentication at all since the prices endpoint is public, but if you want to track usage:

curl -X POST https://merx.exchange/api/v1/keys \
  -H "Authorization: Bearer $JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "website-price-widget",
    "permissions": []
  }'

A key with an empty permissions array can access public endpoints (prices, provider list) while allowing you to track request volume and apply rate limits per key.

Example: Full Trading Bot Key

curl -X POST https://merx.exchange/api/v1/keys \
  -H "Authorization: Bearer $JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "trading-bot-prod",
    "permissions": ["create_orders", "view_orders", "view_balance"]
  }'

Rate Limits

MERX applies rate limits per endpoint category, not per key. All rate limits are measured in requests per minute from the same authenticated identity (API key or JWT session).

Rate Limit Table

Endpoint CategoryRate LimitExamples
Price data300/minGET /prices, GET /prices/history
Order creation10/minPOST /orders
Order queries60/minGET /orders, GET /orders/:id
Withdrawals5/minPOST /withdraw
Account data60/minGET /balance, GET /keys
Key management10/minPOST /keys, DELETE /keys/:id

Rate Limit Headers

Every response includes rate limit information in HTTP headers:

X-RateLimit-Limit: 300
X-RateLimit-Remaining: 287
X-RateLimit-Reset: 1711785660

When You Hit the Limit

Exceeding the rate limit returns HTTP 429 Too Many Requests with a Retry-After header indicating how many seconds to wait:

{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Retry after 12 seconds.",
    "details": {
      "limit": 10,
      "window": "1m",
      "retry_after": 12
    }
  }
}

Handling Rate Limits in Code

The SDKs handle rate limits automatically with configurable retry behavior:

const merx = new MerxClient({
  apiKey: process.env.MERX_API_KEY,
  maxRetries: 3,
  retryOnRateLimit: true, // Automatically wait and retry on 429
});

For raw HTTP clients, implement backoff based on the Retry-After header:

import requests
import time

def merx_request(method, path, **kwargs):
    url = f"https://merx.exchange/api/v1{path}"
    headers = {"X-API-Key": API_KEY}

    for attempt in range(3):
        response = requests.request(method, url, headers=headers, **kwargs)

        if response.status_code == 429:
            retry_after = int(response.headers.get("Retry-After", 10))
            print(f"Rate limited. Waiting {retry_after}s...")
            time.sleep(retry_after)
            continue

        response.raise_for_status()
        return response.json()

    raise Exception("Rate limit retries exhausted")

Лучшие практики безопасности

Store Keys in Environment Variables

Never hardcode API keys in source code. Use environment variables or a secrets manager:

# .env file (never commit this)
MERX_API_KEY=merx_live_k7x9m2p4q8r1s5t3u7v2w6x0y4z...
// Load from environment
const merx = new MerxClient({
  apiKey: process.env.MERX_API_KEY,
});

Rotate Keys Periodically

Create a new key, update your services to use it, then revoke the old key. MERX supports multiple active keys simultaneously, so you can rotate without downtime:

  1. Create a new key with the same permissions.
  2. Deploy the new key to your services.
  3. Verify the new key works in production.
  4. Revoke the old key.

Monitor Key Usage

Review your API key list periodically. Revoke keys that are no longer in use. Each key has a last_used_at timestamp - if a key has not been used in months, it is a candidate for revocation.

Never Expose Keys in Client-Side Code

API keys should never appear in JavaScript running in a browser, mobile app bundles, or any code that end users can inspect. If you need to call MERX from a frontend, proxy the requests through your backend, which holds the API key server-side.

Browser -> Your Backend (holds API key) -> MERX API

Use Separate Keys for Separate Environments

Maintain distinct keys for development, staging, and production. If a development key leaks, it cannot affect production. MERX does not currently have environment-scoped keys, but naming conventions help:

dev-price-monitor
staging-order-bot
prod-order-bot
prod-balance-alerter

Audit on Suspicion

If you suspect a key has been compromised, revoke it immediately and create a replacement. Check your recent order and withdrawal history for unauthorized activity. MERX logs all API key usage with IP addresses, which can help identify the source of unauthorized access.

Собираем все вместе

A complete authentication setup for a production system typically looks like this:

  1. Log in via the web dashboard to get a JWT session.
  2. Create separate API keys for each service: order bot, monitoring, reporting.
  3. Assign minimal permissions to each key.
  4. Store keys in your secrets manager or environment variables.
  5. Implement rate limit handling with automatic retry.
  6. Set up key rotation on a regular schedule (quarterly is reasonable).
  7. Monitor key usage and revoke unused keys.

Authentication is the foundation of every MERX integration. Spending an hour getting it right saves days of debugging and security incidents down the line.


All Articles