Programmatic Access

Authenticate your backend services with Cubewire using OAuth 2.0 client credentials.


Overview

For server-to-server integration, Cubewire uses the OAuth 2.0 Client Credentials flow. Your backend exchanges a client ID and secret for a short-lived access token, then uses that token to authenticate API requests.


Create API Credentials

  1. Sign in to wallet.cubewire.com
  2. Go to SettingsAPI Access
  3. Click Generate Credential
  4. Enter a descriptive name (e.g., "Production Backend", "Staging Server")
  5. Select the roles to assign (determines what the credential can access)
  6. Optionally configure:
    • Expiration date — Credential automatically stops working after this date
    • IP whitelist — Restrict access to specific IP addresses (max 10 entries)
  7. Click Create
  8. Copy the Client ID and Client Secret

Get an Access Token

Exchange your credentials for an access token by calling the token endpoint.

Endpoint: POST /api/v1/oauth2/token

Content-Type: application/x-www-form-urlencoded

ParameterTypeRequiredDescription
grant_typestringYesMust be client_credentials
client_idstringYesYour OAuth2 client ID
client_secretstringYesYour OAuth2 client secret
curl -X POST https://api.cubewire.io/api/v1/oauth2/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET"

Response

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600
}
FieldDescription
access_tokenJWT token for API authentication
token_typeAlways Bearer
expires_inToken lifetime in seconds (3600 = 1 hour)

Make Authenticated Requests

Include the access token in the Authorization header for all API requests:

Authorization: Bearer {access_token}
curl -X GET https://api.cubewire.io/api/v1/vaults \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json"

Token Management

Token Expiration

Access tokens expire after 1 hour (3600 seconds). When a token expires, API requests return 401 Unauthorized.

Handling Expiration

Implement proactive token refresh in your application. Refresh tokens before they expire (recommended: 5 minutes before expiry):

class CubewireClient {
  constructor(clientId, clientSecret) {
    this.clientId = clientId;
    this.clientSecret = clientSecret;
    this.accessToken = null;
    this.tokenExpiry = null;
  }

  async getToken() {
    // Refresh if token is missing or expires within 5 minutes
    const bufferMs = 5 * 60 * 1000;
    if (!this.accessToken || Date.now() >= this.tokenExpiry - bufferMs) {
      await this.refreshToken();
    }
    return this.accessToken;
  }

  async refreshToken() {
    const params = new URLSearchParams({
      grant_type: 'client_credentials',
      client_id: this.clientId,
      client_secret: this.clientSecret
    });

    const response = await fetch('https://api.cubewire.io/api/v1/oauth2/token', {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: params
    });

    const data = await response.json();
    this.accessToken = data.access_token;
    this.tokenExpiry = Date.now() + (data.expires_in * 1000);
  }

  async request(method, path, body = null) {
    const token = await this.getToken();
    
    const options = {
      method,
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
      }
    };
    
    if (body) {
      options.body = JSON.stringify(body);
    }

    const response = await fetch(`https://api.cubewire.io${path}`, options);
    
    if (response.status === 401) {
      // Token might have been revoked, try refreshing once
      await this.refreshToken();
      return this.request(method, path, body);
    }

    return response.json();
  }
}

// Usage
const client = new CubewireClient(
  process.env.CUBEWIRE_CLIENT_ID,
  process.env.CUBEWIRE_CLIENT_SECRET
);

const vaults = await client.request('GET', '/api/v1/vaults');

Credential Permissions

API credentials inherit permissions from their assigned roles. The credential can only access what its roles allow.

Assigning Roles

When creating a credential:

  1. Select one or more roles
  2. The credential inherits all permissions from those roles
  3. Use the principle of least privilege—assign only what's needed

Common Configurations

Use CaseRecommended Roles
Read-only monitoringViewer
Transaction submissionMember
Full automationAdmin
Custom workflowsCustom role with specific permissions

IP Whitelisting

Restrict API access to specific IP addresses for enhanced security.

Supported Formats

FormatExampleDescription
IPv4203.0.113.50Single IP address
CIDR203.0.113.0/24IP range (256 addresses)

Configuration

  • Maximum 10 IP entries per credential
  • Empty whitelist = no IP restriction (any IP allowed)
  • Requests from non-whitelisted IPs are rejected with 403 Forbidden

You can update IP whitelists via the console or API. See API Credentials for management options.


Security Best Practices

Store Secrets Securely

# .env file (never commit to git)
CUBEWIRE_CLIENT_ID=your_client_id
CUBEWIRE_CLIENT_SECRET=your_client_secret
// Access in code
const clientId = process.env.CUBEWIRE_CLIENT_ID;
const clientSecret = process.env.CUBEWIRE_CLIENT_SECRET;

Recommendations

PracticeDescription
Never commit secretsAdd .env to .gitignore; use secrets managers in production
Use HTTPS onlyAll Cubewire endpoints use HTTPS; never disable certificate verification
Rotate credentialsGenerate new credentials periodically; revoke old ones
Monitor access logsReview API usage for unusual patterns
Separate environmentsUse different credentials for development, staging, and production

Error Handling

Authentication Errors

Status CodeErrorSolution
400invalid_grantCheck that grant_type is client_credentials
401invalid_clientVerify client_id and client_secret are correct
401UnauthorizedAccess token is invalid or expired; request a new token
403ForbiddenCredential lacks permission, or IP not whitelisted

Example Error Response

{
  "error": "invalid_client",
  "error_description": "Client authentication failed"
}

Retry Strategy

For 401 Unauthorized on API requests:

  1. Request a new access token
  2. Retry the original request with the new token
  3. If still failing, check if the credential was revoked in the console

Rate Limits

API requests are rate-limited to ensure platform stability.

Limit TypeValue
Token requests10 per minute per credential
API requests100 per second per organization

When rate-limited, you'll receive a 429 Too Many Requests response. Implement exponential backoff:

async function requestWithRetry(fn, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      if (error.status === 429 && i < maxRetries - 1) {
        const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
        await new Promise(resolve => setTimeout(resolve, delay));
        continue;
      }
      throw error;
    }
  }
}

Next