Integration Benefits

Crane Ledger is designed from the ground up for seamless integration into any application. Unlike traditional accounting software with limited APIs and complex integration requirements, Crane Ledger offers unparalleled flexibility through its headless architecture, multi-protocol support, and robust background processing system.

Headless API Architecture

What is Headless?

A headless system separates the backend business logic from the frontend user interface. Crane Ledger has no frontend assumptions - it's pure API that can power any user experience you can imagine.

Integration Advantages

Complete API Coverage

Every feature in Crane Ledger is accessible via API:

  • Chart of Accounts: Create, modify, and query account structures
  • Transactions: Record and manage all financial activities
  • Financial Reports: Generate balance sheets, income statements, trial balances
  • Multi-Organization: Handle complex business hierarchies
  • Multi-Currency: Process international transactions
  • Audit Trails: Access complete financial history

No UI Dependencies

// Traditional accounting software
// ❌ Must use their web interface or limited API
const quickbooks = new QuickBooksClient();
await quickbooks.launchWebInterface(); // Opens browser window

// Crane Ledger
// ✅ Pure API - integrate anywhere
const crane = new CraneLedger({ apiKey: 'cl_live_key' });
const accounts = await crane.accounts.list(); // Returns JSON data

Custom User Experiences

Build accounting interfaces tailored to your users:

  • Embedded Widgets: Accounting components in your existing UI
  • Mobile Apps: Native mobile accounting experiences
  • Voice Interfaces: Accounting via Amazon Alexa, Google Assistant
  • AI Assistants: Accounting operations through chatbots
  • IoT Devices: Accounting data on smart displays

Multi-Protocol Support

Crane Ledger supports multiple communication protocols, each optimized for different use cases.

REST API - Universal Standard

Overview

Industry-standard RESTful API with predictable URLs and HTTP methods.

Best For

  • CRUD Operations: Standard create, read, update, delete workflows
  • Simple Integrations: Straightforward API consumption
  • Caching: HTTP caching headers for performance
  • Debugging: Familiar request/response patterns

Example Usage

// Create account
const response = await fetch('/organizations/org_123/accounts', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer cl_live_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    code: '1001',
    name: 'Operating Cash',
    type: 'asset'
  })
});

// List transactions
const transactions = await fetch('/organizations/org_123/transactions', {
  headers: { 'Authorization': 'Bearer cl_live_key' }
}).then(r => r.json());

GraphQL API - Flexible Querying

Overview

Query exactly the data you need with a single request.

Best For

  • Complex Data Requirements: Related data in one request
  • Mobile Apps: Minimize network requests and data transfer
  • Dynamic UIs: Fetch different data based on user interactions
  • API Exploration: Discover available data during development

Example Usage

const query = `
  query GetOrganizationOverview($orgId: ID!) {
    organization(id: $orgId) {
      name
      accounts {
        code
        name
        balance {
          amount
          formatted
        }
      }
      recentTransactions(limit: 5) {
        description
        amount
        date
      }
    }
  }
`;

const result = await graphql.request(query, {
  orgId: 'org_123'
});

MCP Protocol - AI-Native Integration

Overview

Model Context Protocol for seamless AI assistant integration.

Best For

  • AI Applications: Accounting operations via AI assistants
  • Voice Interfaces: Natural language accounting commands
  • Automated Workflows: AI-driven financial processes
  • Intelligent Agents: Context-aware financial operations

Example Usage

{
  "method": "tools/call",
  "params": {
    "name": "create_invoice",
    "arguments": {
      "organization_id": "org_123",
      "contact_id": "con_456",
      "items": [
        {
          "description": "Consulting Services",
          "quantity": 10,
          "price": 100.00
        }
      ]
    }
  }
}

Worker Architecture Benefits

Asynchronous Processing

Crane Ledger uses a sophisticated worker system for reliable, scalable processing:

Immediate Response + Background Processing

// Complex operations return job IDs immediately
const result = await crane.invoices.create({
  contact_id: 'con_123',
  items: complexItemsArray
});
// Returns: { job_id: 'job_456', status: 'queued' }

// Check status asynchronously
const status = await crane.jobs.get('job_456');
// Returns: { status: 'completed', result: invoiceData }

Benefits

  • No Timeouts: Complex operations don't block your application
  • Reliability: Failed operations automatically retry
  • Scalability: Handle peak loads with background processing
  • User Experience: Immediate feedback with progress tracking

Worker Types

Entity Workers

  • Account Worker: Chart of accounts operations
  • Transaction Worker: Financial transaction processing
  • Invoice Worker: Sales document creation and management
  • Contact Worker: Customer/vendor data management

System Workers

  • Report Worker: Financial statement generation
  • Reconciliation Worker: Bank statement matching
  • Recurring Worker: Scheduled transaction execution
  • Currency Worker: Exchange rate updates

Queue Management

// Monitor worker queues
const queues = await crane.system.queues();
// Returns queue depths, processing rates, error rates

// Prioritize urgent operations
await crane.jobs.prioritize('job_urgent_id', 'high');

// Cancel queued operations
await crane.jobs.cancel('job_unwanted_id');

Integration Patterns

Direct API Integration

Simple Synchronous Operations

class AccountingService {
  constructor(apiKey, orgId) {
    this.apiKey = apiKey;
    this.orgId = orgId;
    this.baseUrl = 'https://api.craneledger.ai';
  }

  async getAccountBalance(accountId) {
    const response = await fetch(
      `${this.baseUrl}/organizations/${this.orgId}/accounts/${accountId}`,
      {
        headers: { 'Authorization': `Bearer ${this.apiKey}` }
      }
    );
    return response.json();
  }
}

Batch Operations

async createBulkContacts(contacts) {
  const jobs = [];

  for (const contact of contacts) {
    const job = await fetch('/organizations/org_123/contacts', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${this.apiKey}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(contact)
    }).then(r => r.json());

    jobs.push(job);
  }

  // Wait for all jobs to complete
  return Promise.all(jobs.map(job => this.pollJobStatus(job.id)));
}

Webhook Integration

Real-Time Event Streaming

// Register webhook endpoint
await crane.webhooks.create({
  url: 'https://your-app.com/webhooks/accounting',
  events: ['transaction.posted', 'invoice.paid'],
  secret: 'webhook_secret'
});

// Handle webhook in your application
app.post('/webhooks/accounting', (req, res) => {
  const event = req.body;

  switch (event.type) {
    case 'transaction.posted':
      updateLocalTransaction(event.data.transaction);
      break;
    case 'invoice.paid':
      markInvoicePaid(event.data.invoice_id);
      break;
  }

  res.sendStatus(200);
});

Third-Party Service Integration

Payment Processor Integration

// Stripe webhook handler
app.post('/webhooks/stripe', async (req, res) => {
  const event = req.body;

  if (event.type === 'payment_intent.succeeded') {
    const payment = event.data.object;

    // Record payment in accounting
    await crane.invoices.recordPayment({
      invoice_id: payment.metadata.invoice_id,
      amount: payment.amount / 100, // Convert cents to dollars
      payment_date: new Date(payment.created * 1000),
      reference: `Stripe: ${payment.id}`
    });
  }

  res.sendStatus(200);
});

Bank Feed Integration

// Automatic bank reconciliation
async processBankTransactions(transactions) {
  for (const txn of transactions) {
    // Check for matching accounting transaction
    const match = await crane.transactions.find({
      amount: txn.amount,
      date: txn.date,
      description: txn.description
    });

    if (match) {
      // Auto-reconcile
      await crane.reconciliations.reconcile({
        transaction_id: match.id,
        bank_transaction_id: txn.id
      });
    } else {
      // Create new transaction
      await crane.transactions.create({
        description: txn.description,
        amount: txn.amount,
        date: txn.date,
        account_id: checkingAccountId
      });
    }
  }
}

Enterprise Integration Features

Multi-Organization Management

Client Isolation for Accounting Firms

class AccountingFirmAPI {
  constructor(firmApiKey) {
    this.firmApiKey = firmApiKey;
  }

  async createClientOrganization(clientData) {
    // Create isolated client org
    const clientOrg = await crane.organizations.createSub({
      parent_id: this.firmOrgId,
      name: clientData.name,
      relationship_type: 'linked', // Data isolation
      billing_type: 'shared'       // Firm manages billing
    });

    // Create client API key
    const clientKey = await crane.apiKeys.create({
      organization_id: clientOrg.id,
      name: `Client Portal - ${clientData.name}`
    });

    return { clientOrg, clientKey };
  }

  async getFirmOverview() {
    // Consolidated view across all clients
    const clients = await crane.organizations.list({
      parent_id: this.firmOrgId
    });

    return Promise.all(
      clients.map(client => crane.reports.trialBalance(client.id))
    );
  }
}

Advanced Security

API Key Management

// Create scoped API keys
const clientKey = await crane.apiKeys.create({
  organization_id: clientOrg.id,
  name: 'Client Portal',
  permissions: ['read', 'write'],
  expires_at: '2024-12-31'
});

// Rotate keys for security
await crane.apiKeys.rotate(clientKey.id);

Audit Trail Integration

// Complete audit history
const auditLog = await crane.events.list({
  organization_id: orgId,
  entity_type: 'transaction',
  date_from: '2024-01-01'
});

// Export for compliance
await crane.events.export({
  format: 'csv',
  date_range: 'last_year'
});

Performance & Reliability

High Availability

  • 99.9% Uptime SLA: Enterprise-grade reliability
  • Global CDN: Fast access worldwide
  • Automatic Failover: Regional redundancy
  • Performance Monitoring: Real-time metrics

Scalability

  • Horizontal Scaling: Add capacity as you grow
  • Rate Limiting: Fair usage across all clients
  • Caching: Intelligent response caching
  • Background Processing: Non-blocking complex operations

Monitoring & Debugging

// API usage metrics
const metrics = await crane.system.metrics({
  period: '24h',
  organization_id: orgId
});
// Returns: request counts, error rates, latency stats

// Debug failed operations
const failedJobs = await crane.jobs.list({
  status: 'failed',
  organization_id: orgId
});

for (const job of failedJobs) {
  const details = await crane.jobs.get(job.id);
  console.log('Failed job:', details.error);
}

Migration Strategies

From Traditional Accounting Software

Data Export/Import

// Export from existing system
const exportData = await quickbooks.exportAll();

// Transform and import to Crane Ledger
const importJob = await crane.import.start({
  source: 'quickbooks',
  data: exportData,
  organization_id: targetOrgId
});

// Monitor import progress
const status = await crane.jobs.poll(importJob.id);

Parallel Operation

// Run both systems during transition
class MigrationBridge {
  async createTransaction(txnData) {
    // Create in both systems
    const [craneTxn, legacyTxn] = await Promise.all([
      crane.transactions.create(txnData),
      legacySystem.createTransaction(txnData)
    ]);

    // Verify consistency
    this.verifyConsistency(craneTxn, legacyTxn);
  }
}

Phased Adoption

  1. Read-Only Integration: Access existing data via Crane Ledger
  2. Dual Writing: Write to both systems during testing
  3. Feature Migration: Move features one at a time
  4. Complete Cutover: Switch entirely to Crane Ledger

SDK Ecosystem

Official SDKs

// JavaScript/TypeScript
import { CraneLedger } from '@craneledger/js-sdk';

const client = new CraneLedger({
  apiKey: 'cl_live_key',
  organizationId: 'org_123'
});

// Type-safe operations
const invoice: Invoice = await client.invoices.create({
  contactId: 'con_456',
  items: [{ description: 'Service', quantity: 1, price: 100 }]
});
# Python
from craneledger import CraneLedger

client = CraneLedger(
    api_key='cl_live_key',
    organization_id='org_123'
)

# Async operations
invoice = await client.invoices.create({
    'contact_id': 'con_456',
    'items': [{'description': 'Service', 'quantity': 1, 'price': 100}]
})
// Rust
use craneledger::CraneLedger;

let client = CraneLedger::new(
    "cl_live_key",
    "org_123"
).await?;

// Compile-time type safety
let invoice = client.invoices().create(InvoiceCreate {
    contact_id: "con_456".to_string(),
    items: vec![InvoiceItem {
        description: "Service".to_string(),
        quantity: Decimal::from(1),
        price: Decimal::from(100)
    }]
}).await?;

Best Practices

Error Handling

async function safeApiCall(operation) {
  try {
    const result = await operation();

    // Check for business logic errors
    if (result.error) {
      await handleBusinessError(result.error);
    }

    return result;
  } catch (error) {
    // Network or server errors
    if (error.status === 429) {
      await delay(1000);
      return safeApiCall(operation); // Retry
    }

    if (error.status === 402) {
      await purchaseCredits();
      return safeApiCall(operation); // Retry with credits
    }

    throw error;
  }
}

Rate Limiting Awareness

class RateLimitedClient {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.requests = 0;
    this.resetTime = Date.now() + 60000;
  }

  async makeRequest(endpoint, options) {
    if (Date.now() > this.resetTime) {
      this.requests = 0;
      this.resetTime = Date.now() + 60000;
    }

    if (this.requests >= 900) { // Leave buffer
      await delay(this.resetTime - Date.now());
    }

    this.requests++;
    return fetch(endpoint, {
      ...options,
      headers: {
        ...options.headers,
        'Authorization': `Bearer ${this.apiKey}`
      }
    });
  }
}

Webhook Security

function verifyWebhook(payload, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(payload))
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

Future-Proofing

Protocol Evolution

Crane Ledger supports multiple protocols to ensure future compatibility:

  • REST API: Industry standard, always supported
  • GraphQL: Evolving query capabilities
  • MCP: AI-native interactions
  • Webhooks: Event-driven integrations
  • WebSocket: Real-time data streaming

API Versioning

// Version-specific endpoints
const v1Client = new CraneLedger({ version: 'v1' });
const v2Client = new CraneLedger({ version: 'v2' });

// Backward compatibility
const legacyResponse = await v1Client.accounts.list();
const modernResponse = await v2Client.accounts.list();

Crane Ledger's headless architecture and multi-protocol support make it the most flexible accounting API available. Whether you're building a simple mobile app or a complex enterprise system, Crane Ledger integrates seamlessly with your technology stack.


Need help?

Create a free account to access our support portal. Once signed in, use the Support tab in your dashboard to submit a support ticket — our team typically responds within 24 hours.