v1.0 API

Build with Fairside

Decentralized membership-based coverage protocol. Integrate our REST API and smart contracts to offer wallet protection in your dApp.

Scroll to explore

Choose Your Integration Method

Integrate Fairside Protocol using our Web SDK for quick setup, or use the Direct API for full control.

Web SDK

Pre-built components and utilities for rapid integration. Handles authentication and contract interactions.

  • Simplified API wrappers
  • TypeScript support
  • Purchase on Abstract chain
View on npm

Direct API Integration

Full control with REST API and smart contract calls. For custom implementations.

  • Purchase on multiple chains
  • REST API for user management
  • Direct smart contract calls
  • Any language/framework
Explore below

Referral Links

No code required. Share your referral link and earn ETH commissions on every purchase.

  • Earn % on purchases
  • Unique referral code
  • Track signups & earnings
  • Claim rewards in ETH
Learn more

Two Payment Methods

OPTION 1

Native Payment (Abstract Chain)

Your integration sends the transaction. Users pay directly on the Abstract network using ETH. You call the smart contract's purchaseMembership function and submit the transaction on behalf of the user.

  • User signs transaction via their wallet
  • Transaction sent to Abstract chain (Chain ID: 2741)
  • Your integration handles contract interaction
  • Immediate on-chain confirmation
OPTION 2

Crypto Payment (NowPayments)

Fairside manages the transaction. Users pay with supported cryptocurrencies (BTC, USDT, USDC, etc.). They simply send tokens to a generated wallet address. Fairside handles the on-chain membership purchase automatically.

  • User sends tokens to provided address
  • Supports BTC, ETH, USDT, USDC, and more
  • Fairside executes on-chain purchase
  • No Abstract chain interaction required

API Endpoints

Environment Base URL
TestNet https://api.test.fairside.dev/v1
MainNet https://api.fairside.io/v1

Contract Addresses (Abstract Chain)

Required only for Native Payment method. These are the FairSideNetwork contract addresses on Abstract chain.

Environment Chain ID FairSideNetwork Contract RPC URL
TestNet 11124 0xCC484a76566e5cc6d4678D08c3214149f275A673 https://api.testnet.abs.xyz
MainNet 2741 0x17aD4490A9181cf01F2Be059765d4f2d8Ee6d8a0 https://api.mainnet.abs.xyz

Wallet-Based Auth Flow

Authenticate users by signing a message with their wallet. All API requests require an API key.

1

Request Auth Message

Generate a unique message for the user to sign

POST /auth/messages
{
  "walletAddress": "0xYourWalletAddress"
}
Response
{
  "authMessage": {
    "nonce": "a1b2c3d4-e5f6-...",
    "walletAddress": "0xYourWalletAddress",
    "message": "Welcome to Fairside! ..."
  }
}

The message field contains the full text to sign, including wallet address and nonce.

2

Sign Message

User signs the authMessage.message with their wallet

JavaScript (ethers.js)
// Sign the message from the auth response
const signature = await signer.signMessage(authMessage.message);
3

Login & Get JWT

Submit signature with the nonce to receive authentication token

POST /auth/login
{
  "walletAddress": "0xYourWalletAddress",
  "nonce": "a1b2c3d4-e5f6-...",
  "signature": "0xSignedMessageHash...",
  "referralCode": "REFERRAL_CODE"
}

Required Headers

api-key Your API key (required for all requests)
Authorization Bearer token for authenticated endpoints

Coverage Management

Check coverage status, manage wallets, and handle membership operations through the API.

GET /membership/check-cover/{walletAddress} Public

Check if a wallet has active coverage. No authentication required.

Response
{
  "statusCode": 200,
  "hasCover": true,
  "isActive": true,
  "validFrom": "2024-01-01T00:00:00.000Z",
  "validUntil": "2025-01-01T00:00:00.000Z",
  "coverAmount": 5,
  "coverID": 42,
  "activeClaims": []
}
GET /membership/wallets Auth Required

Retrieve the list of wallets covered under the user's membership.

POST /membership/add-wallet Auth Required

Add additional wallets to an existing membership.

Request Body
{
  "walletAddresses": ["0xWallet1...", "0xWallet2..."],
  "coverID": 42
}
GET /users/{walletAddress} Auth Required

Retrieve the authenticated user's account information including membership details.

POST /users/terms/accept Auth Required

Accept terms and conditions before purchasing membership.

POST /membership/top-up Public

Record a top-up transaction after executing on-chain.

Request Body
{
  "coverID": 42,
  "walletAddress": "0xWalletAddress...",
  "coveredAmount": 2,
  "transactionHash": "0xTransactionHash..."
}

Native Payment (Abstract Chain)

Purchase and manage memberships directly through the FairSideNetwork contract on Abstract chain. Your integration must send the transaction — users sign with their wallet, and you submit to the Abstract network.

purchaseMembership

payable
function purchaseMembership(
    uint256 costShareBenefit,  // Amount in wei
    address coverAddress,      // Address to cover
    uint256 membershipType     // 0 for MainNet
) external payable

Purchase a new membership with the specified coverage amount.

estimateCost

view
function estimateCost(
    uint256 costShareBenefit,  // Amount in wei
    uint256 accountDuration,   // 0 for new membership
    uint256 membershipTypeId   // 0 for MainNet
) external view returns (uint256)

Calculate the required payment for a membership.

topupMembership

payable
function topupMembership(
    uint256 coverId,
    uint256 costshareBenefit  // Additional amount in wei
) external payable

Increase the coverage amount of an existing membership.

renewMembership

payable
function renewMembership(
    uint256 coverId,
    uint256 costShareBenefit,
    uint256 membershipTypeId
) external payable

Renew an expired or expiring membership.

getAccountMembership

view
function getAccountMembership(
    address account
) external view returns (uint256[])

Get all cover IDs associated with an account.

getMembership

view
function getMembership(
    uint256 coverId
) external view returns (Membership)

Get detailed membership information by cover ID.

Contract Events

NewMembership
event NewMembership(address indexed member, uint256 coverId, uint256 costshareBenefit, address indexed coverAddress, uint8 tokenType, uint256 membershipTypeId)
TopUpCover
event TopUpCover(address indexed member, uint256 coverId, uint256 costshareBenefit, uint8 tokenType)
RenewMembership
event RenewMembership(address indexed member, uint256 indexed coverId, uint256 costshareBenefit, uint8 tokenType)

Pay with Multiple Cryptocurrencies

Allow users to purchase memberships using Bitcoin, USDT, USDC, and other supported cryptocurrencies. Fairside handles the on-chain transaction — users simply send tokens to a generated wallet address on their preferred network.

Real-time Estimates

Get live exchange rates for supported cryptocurrencies. Shows exact amount needed in user's chosen currency.

Secure Payments

Time-limited payment windows, exact amount validation, and real-time transaction confirmation tracking.

Automatic Fulfillment

Once payment is confirmed, membership is automatically purchased on-chain via webhook processing.

POST /nowpayments/estimates API Key Required

Get payment estimates for all supported cryptocurrencies based on coverage amount.

Request Body
{
  "coverAmount": 5
}
Response
{
  "coverAmount": 5,
  "ethAmount": 0.0975,
  "estimates": [
    {
      "currency": "btc",
      "network": "btc",
      "estimatedAmount": 0.00102345
    },
    {
      "currency": "usdt",
      "network": "eth",
      "estimatedAmount": 195.50
    },
    {
      "currency": "usdc",
      "network": "eth",
      "estimatedAmount": 195.45
    }
  ]
}
POST /nowpayments/payments Auth Required

Create a payment intention. Returns payment address and exact amount to send.

Request Body
{
  "coverAmount": 5,
  "membershipTypeId": "0",
  "paymentCurrency": "btc",
  "paymentNetwork": "btc",
  "paymentType": "new_purchase"
}
Response
{
  "paymentId": "550e8400-e29b-41d4-a716-446655440000",
  "paymentAddress": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
  "paymentAmount": 0.00102345,
  "paymentCurrency": "btc",
  "paymentNetwork": "btc",
  "coverAmount": 5,
  "coverCostAmount": 0.0975,
  "expiresAt": "2024-01-15T12:30:00.000Z"
}
GET /nowpayments/payments/{paymentId} Auth Required

Check the status of a payment. Poll this endpoint to track payment progress.

Response
{
  "paymentId": "550e8400-e29b-41d4-a716-446655440000",
  "paymentStatus": "finished",
  "membershipPurchaseStatus": "completed",
  "membershipPurchaseTxHash": "0x1234...abcd",
  "paymentCurrency": "btc",
  "paymentNetwork": "btc",
  "paymentAmount": 0.00102345,
  "coverAmount": 5,
  "coverCostAmount": 0.0975,
  "createdAt": "2024-01-15T12:00:00.000Z",
  "expiresAt": "2024-01-15T12:30:00.000Z"
}
GET /nowpayments/payments Auth Required

List all payments for the authenticated user.

Payment Types

Value Description
new_purchase New membership purchase
topup Top-up existing membership coverage

Payment Statuses

Status Description
waiting Waiting for user to send payment
confirming Payment received, waiting for confirmations
confirmed Payment confirmed on blockchain
finished Payment completed successfully
partially_paid Partial amount received
expired Payment window expired
failed Payment failed

Membership Purchase Statuses

Status Description
pending Waiting for payment to complete
completed Membership purchased on-chain
failed On-chain purchase failed

Crypto Payment Flow

1

Get Estimates

Fetch payment estimates for all supported cryptocurrencies

POST /nowpayments/estimates
{ "coverAmount": 5 }
2

User Selects Currency

Display available currencies and let user choose their preferred payment method

3

Create Payment

Create payment intention with selected currency

POST /nowpayments/payments
{
  "coverAmount": 5,
  "membershipTypeId": "0",
  "paymentCurrency": "btc",
  "paymentNetwork": "btc",
  "paymentType": "new_purchase"
}
4

Display Payment Details

Show user the payment address and exact amount to send. Include countdown timer for expiration.

5

Poll for Status

Poll payment status until completed or expired

GET /nowpayments/payments/{paymentId}
// Poll every 5-10 seconds
// Stop when paymentStatus is "finished" or "expired"
6

Membership Created

When membershipPurchaseStatus is "completed", the membership has been purchased on-chain. The transaction hash is available in membershipPurchaseTxHash.

Supported Cryptocurrencies

The /nowpayments/estimates endpoint returns all currently supported currencies with their networks. Common options include:

BTC Bitcoin (btc network)
ETH Ethereum (eth network)
USDT Tether
USDC USD Coin

Earn with Referral Links

No integration required. Share your unique referral link and earn ETH commissions when users purchase memberships.

1
Get Your Referral Code

Every Fairside user receives a unique referral code upon registration. Find it in your referral dashboard.

2
Share Your Link

Share your referral link on social media, Discord, Telegram, or anywhere your audience is.

https://fairside.io?referralCode=YOUR_CODE
3
Earn Commissions

When users sign up and purchase memberships using your link, you earn a percentage of their purchase.

4
Claim Your ETH

Track your earnings and claim your accumulated ETH rewards anytime from your dashboard.

What You Can Track

📊 Stats
  • Total signups from your link
  • Users who purchased membership
  • Total cover amount generated
💰 Earnings
  • Total earnings in ETH
  • Already claimed amount
  • Claimable balance

Complete Integration Examples

Ready-to-use code examples for both payment methods: Native Payment (Abstract chain) and Crypto Payment (NowPayments).

JavaScript (ethers.js)
import { ethers } from 'ethers';

const API_BASE_URL = 'https://api.fairside.io/v1';
const API_KEY = 'your-api-key';
const NETWORK_CONTRACT = '0x17aD4490A9181cf01F2Be059765d4f2d8Ee6d8a0';

// 1. Generate message to sign
const generateMessage = async (walletAddress) => {
  const response = await fetch(`${API_BASE_URL}/auth/messages`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'api-key': API_KEY,
    },
    body: JSON.stringify({ walletAddress }),
  });
  return response.json();
};

// 2. Login with signed message
const login = async (walletAddress, nonce, signature) => {
  const response = await fetch(`${API_BASE_URL}/auth/login`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'api-key': API_KEY,
    },
    body: JSON.stringify({ walletAddress, nonce, signature }),
  });
  const data = await response.json();
  return data.jwtToken;
};

// 3. Accept terms
const acceptTerms = async (walletAddress, token) => {
  await fetch(`${API_BASE_URL}/users/terms/accept`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'api-key': API_KEY,
      'Authorization': `Bearer ${token}`,
    },
    body: JSON.stringify({ walletAddress }),
  });
};

// 4. Check membership status
const checkMembership = async (walletAddress) => {
  const response = await fetch(
    `${API_BASE_URL}/membership/check-cover/${walletAddress}`,
    { headers: { 'api-key': API_KEY } }
  );
  return response.json();
};

// 5. Purchase membership on Abstract chain
const purchaseMembership = async (signer, coverAmount, coverAddress) => {
  const networkContract = new ethers.Contract(
    NETWORK_CONTRACT,
    FairSideNetworkABI,
    signer
  );

  const amountWei = ethers.parseEther(coverAmount.toString());
  const fee = await networkContract.estimateCost(amountWei, 0, 0);

  const tx = await networkContract.purchaseMembership(
    amountWei,
    coverAddress,
    0, // MainNet membership type
    { value: fee }
  );

  return tx.wait();
};

// Main integration flow
async function main() {
  const provider = new ethers.BrowserProvider(window.ethereum);
  const signer = await provider.getSigner();
  const walletAddress = await signer.getAddress();

  // Auth flow
  const { authMessage } = await generateMessage(walletAddress);
  const signature = await signer.signMessage(authMessage.message);
  const token = await login(walletAddress, authMessage.nonce, signature);

  // Accept terms
  await acceptTerms(walletAddress, token);

  // Check if already has membership
  const membershipStatus = await checkMembership(walletAddress);
  if (membershipStatus.hasCover) {
    console.log('Already has membership');
    return;
  }

  // Purchase membership (5 ETH coverage)
  const receipt = await purchaseMembership(signer, 5, walletAddress);
  console.log('Membership purchased:', receipt.hash);
}
JavaScript - Crypto Payment Flow
const API_BASE_URL = 'https://api.fairside.io/v1';
const API_KEY = 'your-api-key';
const POLLING_INTERVAL = 10000; // 10 seconds

// 1. Get payment estimates for all supported currencies
async function getPaymentEstimates(coverAmount) {
  const response = await fetch(`${API_BASE_URL}/nowpayments/estimates`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'api-key': API_KEY,
    },
    body: JSON.stringify({ coverAmount }),
  });
  
  const data = await response.json();
  // Returns: { coverAmount, ethAmount, estimates: [{ currency, network, estimatedAmount }] }
  return data;
}

// 2. Create payment intention with selected currency
async function createPayment(token, params) {
  const response = await fetch(`${API_BASE_URL}/nowpayments/payments`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'api-key': API_KEY,
      'Authorization': `Bearer ${token}`,
    },
    body: JSON.stringify({
      coverAmount: params.coverAmount,
      membershipTypeId: '0', // MainNet
      paymentCurrency: params.currency,  // e.g., 'usdt', 'btc'
      paymentNetwork: params.network,    // e.g., 'erc20', 'bitcoin'
      paymentType: 'new_purchase',       // or 'topup'
    }),
  });
  
  const data = await response.json();
  // Returns: { paymentId, paymentAddress, paymentAmount, expiresAt, ... }
  return data;
}

// 3. Poll payment status until complete
async function pollPaymentStatus(token, paymentId, onStatusUpdate) {
  const checkStatus = async () => {
    const response = await fetch(
      `${API_BASE_URL}/nowpayments/payments/${paymentId}`,
      {
        headers: {
          'api-key': API_KEY,
          'Authorization': `Bearer ${token}`,
        },
      }
    );
    
    const status = await response.json();
    onStatusUpdate(status);
    
    // Payment statuses: waiting, confirming, confirmed, sending, finished, failed, expired
    if (status.paymentStatus === 'finished') {
      console.log('Payment complete! Tx:', status.membershipPurchaseTxHash);
      return status;
    }
    
    if (status.paymentStatus === 'failed' || status.paymentStatus === 'expired') {
      throw new Error(`Payment ${status.paymentStatus}`);
    }
    
    // Continue polling
    await new Promise(resolve => setTimeout(resolve, POLLING_INTERVAL));
    return checkStatus();
  };
  
  return checkStatus();
}

// Complete Crypto Payment Flow
async function purchaseWithCrypto(token, coverAmount, preferredCurrency = 'usdt') {
  // Step 1: Get estimates
  const estimates = await getPaymentEstimates(coverAmount);
  console.log('Available currencies:', estimates.estimates);
  
  // Step 2: Find preferred currency
  const selected = estimates.estimates.find(
    e => e.currency === preferredCurrency
  );
  
  if (!selected) {
    throw new Error(`Currency ${preferredCurrency} not available`);
  }
  
  // Step 3: Create payment
  const payment = await createPayment(token, {
    coverAmount,
    currency: selected.currency,
    network: selected.network,
  });
  
  console.log('Send exactly', payment.paymentAmount, selected.currency);
  console.log('To address:', payment.paymentAddress);
  console.log('Expires at:', payment.expiresAt);
  
  // Step 4: Poll until user sends payment and it's confirmed
  // Fairside handles the on-chain membership purchase automatically
  const finalStatus = await pollPaymentStatus(token, payment.paymentId, (status) => {
    console.log('Status:', status.paymentStatus);
  });
  
  return finalStatus;
}

// Usage
purchaseWithCrypto(authToken, 5, 'usdt')
  .then(status => console.log('Membership created:', status.membershipPurchaseTxHash))
  .catch(err => console.error('Payment failed:', err));
JavaScript (ethers.js)
import { ethers } from 'ethers';

const NETWORK_CONTRACT = '0x17aD4490A9181cf01F2Be059765d4f2d8Ee6d8a0';

// FairSideNetwork ABI (minimal)
const FairSideNetworkABI = [
  'function purchaseMembership(uint256 costShareBenefit, address coverAddress, uint256 membershipType) external payable',
  'function estimateCost(uint256 costShareBenefit, uint256 accountDuration, uint256 membershipTypeId) external view returns (uint256)',
  'function getAccountMembership(address account) external view returns (uint256[])',
];

async function purchaseMembership(coverAmountETH) {
  const provider = new ethers.BrowserProvider(window.ethereum);
  const signer = await provider.getSigner();
  const walletAddress = await signer.getAddress();
  
  const networkContract = new ethers.Contract(
    NETWORK_CONTRACT,
    FairSideNetworkABI,
    signer
  );

  // Check if user already has membership
  const coverIds = await networkContract.getAccountMembership(walletAddress);
  if (coverIds.length >= 1) {
    throw new Error('User already has a membership');
  }

  // Calculate cost
  const amountWei = ethers.parseEther(coverAmountETH.toString());
  const fee = await networkContract.estimateCost(amountWei, 0, 0);

  // Purchase
  const tx = await networkContract.purchaseMembership(
    amountWei,
    walletAddress,
    0, // MainNet type
    { value: fee }
  );

  const receipt = await tx.wait();
  console.log('Transaction hash:', receipt.hash);
  
  return receipt;
}

// Usage
purchaseMembership(5); // 5 ETH coverage
JavaScript
const API_BASE_URL = 'https://api.fairside.io/v1';
const API_KEY = 'your-api-key';

async function checkCoverageStatus(walletAddress) {
  const response = await fetch(
    `${API_BASE_URL}/membership/check-cover/${walletAddress}`,
    {
      headers: {
        'api-key': API_KEY,
      },
    }
  );

  const data = await response.json();
  
  return {
    hasCoverage: data.hasCover,
    isActive: data.isActive,
    coverAmount: data.coverAmount,
    validUntil: new Date(data.validUntil),
    hasActiveClaims: data.activeClaims.length > 0,
  };
}

// Usage
const status = await checkCoverageStatus('0x...');

if (status.hasCoverage && status.isActive) {
  console.log(`Protected with ${status.coverAmount} ETH until ${status.validUntil}`);
} else if (status.hasCoverage && !status.isActive) {
  console.log('Coverage expired - renewal needed');
} else {
  console.log('No coverage - purchase needed');
}

Error Handling

API Errors

400 Bad Request - Invalid input
401 Unauthorized - Invalid or expired token
403 Forbidden - Access denied
404 Not Found - Resource not found
500 Internal Server Error

Contract Errors

"Only one cover allowed" User already has active membership
"Capital pool not funded" Protocol capital pool is empty
"Cover amount invalid" Amount < 0.25 ETH or > 10 ETH
"Cannot top-up during claim" Cover blocked due to ongoing claim

Ready to integrate?

Get your API key and start building wallet protection into your dApp.