Authentication Guide

All Neutron API requests require authentication. This guide covers how to generate signatures, get access tokens, and use them securely.

How It Works

  1. Generate a signature using your API Key and Secret (HMAC-SHA256)
  2. Exchange for an access token via the authentication endpoint
  3. Use the token as a Bearer token in all API calls

Signature Formula

stringToSign = "{apiKey}&payload={jsonPayload}"
signature    = HMAC-SHA256(apiSecret, stringToSign) -> hex

The payload can be any valid JSON (e.g., {"test":"auth"}). The same JSON is sent as the request body.

Code Examples

Node.js

const crypto = require('crypto');

function authenticate(apiKey, apiSecret) {
  const payload = JSON.stringify({ test: 'auth' });
  const stringToSign = `${apiKey}&payload=${payload}`;
  const signature = crypto
    .createHmac('sha256', apiSecret)
    .update(stringToSign)
    .digest('hex');

  return fetch('https://api.neutron.me/api/v2/authentication/token-signature', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Api-Key': apiKey,
      'X-Api-Signature': signature,
    },
    body: payload,
  }).then(res => res.json());
}

const { accessToken, accountId } = await authenticate('your-api-key', 'your-api-secret');

Python

import hmac
import hashlib
import json
import requests

def authenticate(api_key, api_secret):
    payload = json.dumps({"test": "auth"})
    string_to_sign = f"{api_key}&payload={payload}"
    signature = hmac.new(
        api_secret.encode(),
        string_to_sign.encode(),
        hashlib.sha256
    ).hexdigest()

    response = requests.post(
        'https://api.neutron.me/api/v2/authentication/token-signature',
        headers={
            'Content-Type': 'application/json',
            'X-Api-Key': api_key,
            'X-Api-Signature': signature,
        },
        data=payload,
    )
    return response.json()

result = authenticate('your-api-key', 'your-api-secret')
access_token = result['accessToken']

Go

func authenticate(apiKey, apiSecret string) (string, error) {
    payload := `{"test":"auth"}`
    stringToSign := apiKey + "&payload=" + payload
    h := hmac.New(sha256.New, []byte(apiSecret))
    h.Write([]byte(stringToSign))
    signature := hex.EncodeToString(h.Sum(nil))

    req, _ := http.NewRequest("POST",
        "https://api.neutron.me/api/v2/authentication/token-signature",
        strings.NewReader(payload))
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("X-Api-Key", apiKey)
    req.Header.Set("X-Api-Signature", signature)

    resp, err := http.DefaultClient.Do(req)
    // ... parse response for accessToken
}

PHP

function authenticate($apiKey, $apiSecret) {
    $payload = json_encode(['test' => 'auth']);
    $stringToSign = "{$apiKey}&payload={$payload}";
    $signature = hash_hmac('sha256', $stringToSign, $apiSecret);

    $ch = curl_init('https://api.neutron.me/api/v2/authentication/token-signature');
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Content-Type: application/json',
        "X-Api-Key: {$apiKey}",
        "X-Api-Signature: {$signature}",
    ]);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    return json_decode(curl_exec($ch), true);
}

cURL / Bash

API_KEY="your-api-key"
API_SECRET="your-api-secret"
PAYLOAD='{"test":"auth"}'
STRING_TO_SIGN="${API_KEY}&payload=${PAYLOAD}"
SIGNATURE=$(echo -n "$STRING_TO_SIGN" | openssl dgst -sha256 -hmac "$API_SECRET" | cut -d' ' -f2)

curl -X POST https://api.neutron.me/api/v2/authentication/token-signature \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: $API_KEY" \
  -H "X-Api-Signature: $SIGNATURE" \
  -d "$PAYLOAD"

Response

{
  "accessToken": "eyJhbGciOiJIUzI1NiIs...",
  "expiredAt": 1770428400000,
  "accountId": "ne01-abc123def456"
}

Using the Token

Include the token in the Authorization header for all API calls:

curl https://api.neutron.me/api/v2/account/YOUR_ACCOUNT_ID \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Token Management

  • Tokens have a limited validity period -- check expiredAt
  • Using an expired token returns 401 Unauthorized
  • No refresh token flow -- simply re-authenticate when expired

Auto-Refresh Pattern

class NeutronClient {
  constructor(apiKey, apiSecret) {
    this.apiKey = apiKey;
    this.apiSecret = apiSecret;
    this.token = null;
    this.tokenExpiry = null;
  }

  async getToken() {
    if (!this.token || Date.now() > this.tokenExpiry - 300000) {
      const result = await authenticate(this.apiKey, this.apiSecret);
      this.token = result.accessToken;
      this.tokenExpiry = result.expiredAt;
    }
    return this.token;
  }
}

Security Best Practices

Do: Store secrets in env vars or secret managers. Rotate keys periodically. Restrict key permissions to what's needed.

Don't: Expose secrets in client-side code. Commit secrets to git. Share secrets over chat.