Skip to main content
Explore common integration scenarios and learn how to implement them using the ClearLine POS API. Each use case includes a business overview, technical approach, required endpoints, and working code examples.

🛒 Process POS Transaction → Trigger Loyalty

When a customer completes a purchase at the point of sale, automatically record the transaction and award loyalty points or trigger marketing actions based on their purchase behavior.
This workflow involves three key steps:
  1. Start Interaction - Initialize a POS session for the terminal
  2. Send Transaction - Submit transaction details with customer data, items, amounts, and payment info
  3. Handle Response - Process loyalty points awarded and any triggered campaigns
API Endpoints Used:
// Step 1: Start POS session
const interactionResponse = await fetch('https://public-api-demo.clearline.me/pos/clover/startInteraction', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    terminalId: "TERM-05",
    posLocationId: "LOC123"
  })
});

const { data } = await interactionResponse.json();
const sessionId = data.sessionId;

// Step 2: Send transaction with customer data
const transactionResponse = await fetch('https://public-api-demo.clearline.me/pos/clover/transaction', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    sessionId: sessionId,
    posLocationId: "LOC123",
    terminalId: "TERM-05",
    transactionId: "TXN-" + Date.now(),
    transactionAmount: 12.97,
    customer: {
      id: "CUST-001",
      firstName: "John",
      lastName: "Doe",
      contacts: [
        { type: "Email", value: "john.doe@example.com" },
        { type: "Phone", value: "+15555551234" }
      ]
    },
    products: [
      { 
        productId: "COFFEE-001", 
        productName: "Large Coffee", 
        price: 3.99, 
        quantity: 2,
        totalPrice: 7.98
      },
      { 
        productId: "MUFFIN-002", 
        productName: "Blueberry Muffin", 
        price: 4.99, 
        quantity: 1,
        totalPrice: 4.99
      }
    ]
  })
});

const result = await transactionResponse.json();
console.log('Transaction processed:', result);

// Check loyalty response
if (result.data.loyalty) {
  console.log('Loyalty points awarded:', result.data.loyalty);
}
Include customer contact information in the transaction request to enable loyalty tracking and marketing campaign triggers.

Learn More

View complete transaction API reference →

🎟️ Validate Coupon at Checkout

Enable cashiers to scan or enter coupon codes during checkout and validate them in real-time before applying discounts.
Workflow:
  1. Lookup Coupon - Search for a coupon by code
  2. Validate Coupon - Check coupon status and eligibility
  3. Apply Discount - Use coupon information to calculate discount in your POS
  4. Record Usage - Include coupon details in the transaction
API Endpoints Used:
The validate endpoint confirms the coupon exists and is active. Your POS system is responsible for applying business rules like minimum purchase amounts and calculating the actual discount.
// Step 1: Lookup coupon by code
const lookupResponse = await fetch('https://public-api-demo.clearline.me/v2/pos/clover/coupon/couponCodes/lookup', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    posLocationId: "LOC123",
    code: "SAVE20"
  })
});

const lookupResult = await lookupResponse.json();

if (!lookupResult.data?.couponCodes || lookupResult.data.couponCodes.length === 0) {
  console.error('Coupon not found');
  return;
}

const couponDetails = lookupResult.data.couponCodes[0];
console.log('Coupon found:', couponDetails);

// Step 2: Validate coupon
const validateResponse = await fetch('https://public-api-demo.clearline.me/v2/pos/clover/coupon/couponCodes/validate', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    posLocationId: "LOC123",
    code: "SAVE20",
    rewardProvider: "TwoReward" // Optional: specify reward provider
  })
});

const validation = await validateResponse.json();

if (validation.success) {
  console.log('Coupon is valid and can be applied');
  // Your POS calculates the discount based on coupon details
} else {
  console.error('Coupon validation failed');
}
These endpoints verify coupon existence and status. Your POS system must implement discount calculation logic based on the coupon details returned.

Learn More

View complete coupons API reference →

📺 Display Marketing Content with Widgets

Show interactive marketing content on customer-facing displays that customers can engage with to join loyalty programs, view offers, or receive digital receipts via QR code or SMS.
Workflow:
  1. List Widgets - Get available marketing actions for the location
  2. Start Widget Session - Launch a widget for customer interaction
  3. Show QR Code - Display QR code for mobile engagement
  4. Send Message - Deliver content via SMS/email
API Endpoints Used:Widget Types:
  • Loyalty enrollment
  • Promotion signup
  • Digital receipt delivery
  • Survey/feedback collection
// Step 1: Get available widgets
const widgetsResponse = await fetch('https://public-api-demo.clearline.me/v2/pos/clover/widget/list', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    posLocationId: "LOC123"
  })
});

const { data: widgets } = await widgetsResponse.json();
console.log('Available widgets:', widgets);

// Step 2: Start widget session
const startResponse = await fetch('https://public-api-demo.clearline.me/v2/pos/clover/widget/start', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    posLocationId: "LOC123",
    terminalId: "TERM-05",
    widgetId: widgets[0].id
  })
});

const { data: session } = await startResponse.json();

// Step 3: Show QR code
const qrResponse = await fetch('https://public-api-demo.clearline.me/v2/pos/clover/widget/showQrCode', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    sessionId: session.sessionId,
    posLocationId: "LOC123"
  })
});

const { data: qrData } = await qrResponse.json();
console.log('QR code URL:', qrData.qrCodeHtmlLinkUrl);
Widgets are configured in the ClearLine admin portal. The list endpoint returns only active widgets for your location.

Learn More

View complete widgets API reference →

🔄 Sync Product Catalog

Maintain an up-to-date product catalog in ClearLine by automatically syncing products, categories, and promotions from your POS or inventory management system on a scheduled basis.
Sync Strategies:
StrategyWhen to UsePerformance
Full SyncInitial setup, weekly refreshSlower, comprehensive
Incremental SyncDaily updates, changed items onlyFaster, efficient
On-Demand SyncImmediate updates for specific itemsFastest, targeted
API Endpoints Used:
  • POST /pos/{posSystemId}/company/{posCompanyId}/import/products - Import products
  • POST /pos/{posSystemId}/company/{posCompanyId}/import/productCategories - Import categories
  • POST /pos/{posSystemId}/company/{posCompanyId}/import/promotions - Import promotions
Data Requirements:
  • Product ID (unique identifier)
  • Product name
  • Price and category
  • Manufacturer (optional)
// Scheduled nightly sync
async function nightlyCatalogSync() {
  try {
    console.log('Starting nightly catalog sync...');
    
    // Fetch products from your POS system
    const posProducts = await fetchProductsFromPOS();
    
    // Transform to ClearLine format
    const products = posProducts.map(p => ({
      productId: p.itemId,
      productName: p.itemName,
      price: p.unitPrice,
      productCategoryId: p.categoryCode,
      manufacturer: p.manufacturer
    }));
    
    // Import products in batches
    const response = await fetch('https://public-api-demo.clearline.me/pos/clover/company/comp123/import/products', {
      method: 'POST',
      headers: {
        'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        items: products
      })
    });
    
    const result = await response.json();
    console.log('Import result:', result);
    
  } catch (error) {
    console.error('Catalog sync failed:', error);
  }
}

// Run at 2 AM daily
// cron: 0 2 * * *
Optimization Tips:
  • Batch products in groups of 500-1000 for optimal performance
  • Schedule during off-peak hours (2-5 AM)
  • Implement retry logic with exponential backoff
  • Monitor sync completion and error rates

Learn More

View complete import API reference →

🔧 Error Recovery & Retry Logic

Build resilient POS integrations that gracefully handle network failures, API errors, and timeout scenarios without losing transaction data or frustrating customers.
Common Error Scenarios:
  • Network timeouts (slow connection)
  • 5xx server errors (temporary API issues)
  • 4xx client errors (invalid requests)
  • Authentication failures (expired tokens)
  • Rate limiting (too many requests)
Retry Strategies:
Error TypeRetry StrategyMax Retries
Network TimeoutExponential backoff3
5xx Server ErrorExponential backoff3
429 Rate LimitWait for Retry-After header2
401 UnauthorizedRefresh token once1
4xx Client ErrorNo retry (fix request)0
Best Practices:
  • Implement exponential backoff (1s, 2s, 4s, 8s…)
  • Log all retry attempts for debugging
  • Queue failed transactions for later submission
  • Display clear error messages to cashiers
  • Provide manual retry option in POS UI
// Robust API client with retry logic
class ClearLineAPIClient {
  constructor(accessToken) {
    this.accessToken = accessToken;
    this.baseUrl = 'https://public-api-demo.clearline.me';
    this.maxRetries = 3;
  }

  async makeRequest(endpoint, options, retryCount = 0) {
    try {
      const response = await fetch(`${this.baseUrl}${endpoint}`, {
        ...options,
        headers: {
          'Authorization': `Bearer ${this.accessToken}`,
          'Content-Type': 'application/json',
          ...options.headers
        },
        timeout: 30000 // 30 second timeout
      });

      // Handle rate limiting
      if (response.status === 429) {
        const retryAfter = response.headers.get('Retry-After') || 5;
        console.log(`Rate limited. Retrying after ${retryAfter} seconds...`);

        if (retryCount < 2) {
          await this.sleep(retryAfter * 1000);
          return this.makeRequest(endpoint, options, retryCount + 1);
        }
      }

      // Handle authentication failures
      if (response.status === 401) {
        console.log('Access token expired. Refreshing...');
        await this.refreshAccessToken();
        return this.makeRequest(endpoint, options, retryCount + 1);
      }

      // Handle server errors with exponential backoff
      if (response.status >= 500 && retryCount < this.maxRetries) {
        const backoffTime = Math.pow(2, retryCount) * 1000; // 1s, 2s, 4s
        console.log(`Server error. Retrying in ${backoffTime}ms...`);

        await this.sleep(backoffTime);
        return this.makeRequest(endpoint, options, retryCount + 1);
      }

      // Handle client errors (4xx) - don't retry
      if (response.status >= 400 && response.status < 500) {
        const error = await response.json();
        throw new Error(`Client error: ${error.message || response.statusText}`);
      }

      return await response.json();

    } catch (error) {
      // Network/timeout errors
      if (error.name === 'AbortError' || error.message.includes('timeout')) {
        if (retryCount < this.maxRetries) {
          const backoffTime = Math.pow(2, retryCount) * 1000;
          await this.sleep(backoffTime);
          return this.makeRequest(endpoint, options, retryCount + 1);
        }
      }

      // Queue for later retry
      await this.queueFailedRequest(endpoint, options);
      throw error;
    }
  }

  sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  async queueFailedRequest(endpoint, options) {
    // Store in local database for later retry
    console.log('Request queued for later retry');
  }

  async refreshAccessToken() {
    // Implement token refresh logic
  }
}

// Usage
const client = new ClearLineAPIClient('YOUR_ACCESS_TOKEN');
await client.makeRequest('/pos/clover/transaction', {
  method: 'POST',
  body: JSON.stringify({ /* transaction data */ })
});
Monitoring & Alerting:
  • Track retry rates in your monitoring system
  • Alert on high failure rates (>5% of requests)
  • Monitor average retry count per request
  • Set up alerts for queue depth (>100 failed requests)

Learn More

View error handling best practices →

Next Steps