Skip to main content
Quick Start: Get your API keys from the StateSet Dashboard and make your first authenticated request in minutes.

🔐 Overview

StateSet uses API keys to authenticate requests. Authentication is performed via HTTP headers using the Bearer token format. All API requests must be made over HTTPS.

🔑 API Key Types

Test Mode

Prefix: sk_test_Use for development and testing. Transactions are simulated and no real money moves.

Live Mode

Prefix: sk_live_Use for production. All transactions are real and irreversible.
Never expose your secret API keys in client-side code, public repositories, or anywhere else accessible to the public.

📋 Authentication Methods

Standard Authentication

Include your API key in the Authorization header:
curl https://api.stateset.com/v1/account/balance \
  -H "Authorization: Bearer sk_test_your_actual_key_here"

SDK Authentication

When using our official SDKs, initialize with your API key:
import { StateSet } from '@stateset/sdk';

const stateset = new StateSet({
  apiKey: process.env.STATESET_API_KEY // Best practice: use environment variables
});

🛡️ Security Best Practices

Never hardcode API keys in your source code. Use environment variables:
.env
    STATESET_API_KEY=sk_test_your_actual_key_here
// Load from environment
const apiKey = process.env.STATESET_API_KEY;
Regularly rotate your API keys (recommended every 90 days):
  1. Generate a new API key in the dashboard
  2. Update your application to use the new key
  3. Verify everything works correctly
  4. Revoke the old key
  • Development: Use test keys with limited permissions
  • Staging: Use test keys with production-like permissions
  • Production: Use live keys with minimal required permissions
Create keys with only the permissions needed:
// Dashboard API
const key = await stateset.apiKeys.create({
  name: 'Read-only Analytics Key',
  permissions: ['analytics:read', 'transactions:read']
});
Track API key usage to detect anomalies:
const usage = await stateset.apiKeys.usage({
  keyId: 'key_abc123',
  startDate: '2024-01-01',
  endDate: '2024-01-31'
});

🔒 Advanced Authentication

HMAC Signatures (High-Security Operations)

For sensitive operations like large transfers or issuance, add HMAC signatures:
const crypto = require('crypto');

function createHmacSignature(payload, secret) {
  const timestamp = Math.floor(Date.now() / 1000);
  const message = `${timestamp}.${JSON.stringify(payload)}`;
  
  const signature = crypto
    .createHmac('sha256', secret)
    .update(message)
    .digest('hex');
    
  return {
    signature,
    timestamp
  };
}

// Use in request
const payload = { amount: '10000.00', to: 'stateset1abc...' };
const { signature, timestamp } = createHmacSignature(payload, process.env.HMAC_SECRET);

const response = await axios.post('https://api.stateset.com/v1/stablecoin/transfer', payload, {
  headers: {
    'Authorization': `Bearer ${apiKey}`,
    'X-Signature': signature,
    'X-Timestamp': timestamp
  }
});

OAuth 2.0 (Partner Integrations)

For third-party integrations, use OAuth 2.0:
// 1. Redirect user to authorize
const authUrl = `https://auth.stateset.com/oauth/authorize?
  client_id=${CLIENT_ID}&
  redirect_uri=${REDIRECT_URI}&
  response_type=code&
  scope=payments:read+payments:write`;

// 2. Exchange code for token
const tokenResponse = await axios.post('https://auth.stateset.com/oauth/token', {
  grant_type: 'authorization_code',
  code: authorizationCode,
  client_id: CLIENT_ID,
  client_secret: CLIENT_SECRET,
  redirect_uri: REDIRECT_URI
});

// 3. Use access token
const response = await axios.get('https://api.stateset.com/v1/payments', {
  headers: {
    'Authorization': `Bearer ${tokenResponse.data.access_token}`
  }
});

📊 Rate Limits

API keys have different rate limits based on your plan:
PlanRequests/SecondRequests/DayBurst Limit
Free101,00020
Starter100100,000200
Growth1,00010,000,0002,000
EnterpriseCustomCustomCustom

Handling Rate Limits

async function makeRequestWithRetry(url, options, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await axios.get(url, options);
      return response.data;
    } catch (error) {
      if (error.response?.status === 429) {
        const retryAfter = error.response.headers['retry-after'] || 2 ** i;
        console.log(`Rate limited. Retrying after ${retryAfter} seconds...`);
        await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
      } else {
        throw error;
      }
    }
  }
  throw new Error('Max retries exceeded');
}

🚨 Error Responses

Authentication errors return standardized responses:
{
  "error": {
    "type": "authentication_error",
    "message": "Invalid API key provided",
    "code": "invalid_api_key",
    "status": 401
  }
}
Common authentication errors:
Error CodeDescriptionSolution
missing_api_keyNo API key providedInclude Authorization header
invalid_api_keyAPI key is invalidCheck key format and validity
expired_api_keyAPI key has expiredGenerate a new key
insufficient_permissionsKey lacks required permissionsUse a key with proper permissions
rate_limit_exceededToo many requestsImplement backoff and retry

🔄 Key Management API

Programmatically manage your API keys:
// List all keys
const keys = await stateset.apiKeys.list();

// Create a new key
const newKey = await stateset.apiKeys.create({
  name: 'Mobile App Key',
  permissions: ['payments:create', 'payments:read'],
  expires_at: '2024-12-31T23:59:59Z'
});

// Revoke a key
await stateset.apiKeys.revoke('key_abc123');

// Update key permissions
await stateset.apiKeys.update('key_abc123', {
  permissions: ['payments:read']
});

🧪 Testing Authentication

Use our test endpoint to verify your authentication:
curl https://api.stateset.com/v1/auth/test \
  -H "Authorization: Bearer sk_test_your_actual_key_here"
Success response:
{
  "authenticated": true,
  "key_id": "key_abc123",
  "permissions": ["payments:create", "payments:read"],
  "mode": "test"
}

📱 Mobile & Frontend Security

Never use secret API keys in mobile apps or frontend code. Use our public keys or implement a backend proxy.

Public Keys (Read-Only Operations)

// Safe to use in frontend
const publicKey = 'pk_test_TYooMQauvdEDq54NiTphI7jx';

// Limited to read-only operations
const balance = await fetch(`https://api.stateset.com/v1/public/balance/${address}`, {
  headers: {
    'Authorization': `Bearer ${publicKey}`
  }
});

Backend Proxy Pattern

// Frontend
const response = await fetch('/api/stateset-proxy/payment', {
  method: 'POST',
  body: JSON.stringify({ amount: 100, recipient: 'stateset1abc...' })
});

// Backend (Node.js/Express)
app.post('/api/stateset-proxy/payment', authenticate, async (req, res) => {
  const payment = await stateset.payments.create({
    ...req.body,
    customer: req.user.id
  });
  res.json(payment);
});

🆘 Troubleshooting

  • Verify API key is correct and properly formatted
  • Check if key is expired or revoked
  • Ensure Bearer prefix is included
  • Confirm using correct environment (test vs live)
  • Check if key has required permissions
  • Verify you’re not exceeding rate limits
  • Ensure accessing allowed endpoints for key type
Run diagnostics:
curl -v https://api.stateset.com/v1/auth/test \
  -H "Authorization: Bearer YOUR_API_KEY"
Check response headers and body for details.

📚 Next Steps