My App

Getting Started

Quick start guide for the GLAPI API

Getting Started with GLAPI

This guide will help you get started with the GLAPI API in just a few minutes.

Prerequisites

Before you begin, you'll need:

  1. GLAPI Account: Sign up at glapi.io
  2. API Token: Generate from your account settings
  3. Organization: You'll be assigned an organization upon signup

Step 1: Get Your API Token

Web Application

  1. Log into the GLAPI web application
  2. Navigate to your profile settings
  3. Click on "API Access"
  4. Copy your API token

Store Your Token Securely

Save your token as an environment variable:

# .env file
GLAPI_TOKEN=your_token_here

Never commit your token to version control!

Step 2: Make Your First API Call

Using cURL

curl -H "Authorization: Bearer YOUR_TOKEN" \\
  https://api.glapi.io/api/customers

Using TypeScript/JavaScript

const API_TOKEN = process.env.GLAPI_TOKEN;

const response = await fetch('https://api.glapi.io/api/customers', {
  headers: {
    'Authorization': `Bearer ${API_TOKEN}`,
    'Content-Type': 'application/json',
  },
});

const customers = await response.json();
console.log(customers);

Using Python

import os
import requests

API_TOKEN = os.environ.get('GLAPI_TOKEN')

response = requests.get(
    'https://api.glapi.io/api/customers',
    headers={'Authorization': f'Bearer {API_TOKEN}'}
)

customers = response.json()
print(customers)

Step 3: Create Your First Customer

cURL

curl -X POST \\
  -H "Authorization: Bearer YOUR_TOKEN" \\
  -H "Content-Type: application/json" \\
  -d '{
    "companyName": "Acme Corporation",
    "contactEmail": "contact@acme.com",
    "status": "active"
  }' \\
  https://api.glapi.io/api/customers

TypeScript/JavaScript

const newCustomer = await fetch('https://api.glapi.io/api/customers', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${API_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    companyName: 'Acme Corporation',
    contactEmail: 'contact@acme.com',
    status: 'active',
  }),
});

const customer = await newCustomer.json();
console.log('Created customer:', customer.id);

Python

response = requests.post(
    'https://api.glapi.io/api/customers',
    headers={'Authorization': f'Bearer {API_TOKEN}'},
    json={
        'companyName': 'Acme Corporation',
        'contactEmail': 'contact@acme.com',
        'status': 'active',
    }
)

customer = response.json()
print(f"Created customer: {customer['id']}")

Step 4: Retrieve the Customer

Use the ID from the previous step:

curl -H "Authorization: Bearer YOUR_TOKEN" \\
  https://api.glapi.io/api/customers/CUSTOMER_ID

Step 5: Update the Customer

curl -X PUT \\
  -H "Authorization: Bearer YOUR_TOKEN" \\
  -H "Content-Type: application/json" \\
  -d '{
    "contactPhone": "+1-555-0123",
    "billingAddress": {
      "street": "123 Main St",
      "city": "San Francisco",
      "state": "CA",
      "postalCode": "94105",
      "country": "USA"
    }
  }' \\
  https://api.glapi.io/api/customers/CUSTOMER_ID

For TypeScript applications, we recommend using the native tRPC client for type-safe API calls:

Installation

npm install @trpc/client @glapi/trpc superjson

Setup

import { createTRPCClient, httpBatchLink } from '@trpc/client';
import type { AppRouter } from '@glapi/trpc';
import superjson from 'superjson';

const client = createTRPCClient<AppRouter>({
  links: [
    httpBatchLink({
      url: 'https://api.glapi.io/api/trpc',
      headers: () => ({
        Authorization: `Bearer ${process.env.GLAPI_TOKEN}`,
      }),
      transformer: superjson,
    }),
  ],
});

Usage

// List customers (type-safe!)
const customers = await client.customers.list.query();

// Get a customer
const customer = await client.customers.get.query({
  id: 'customer-uuid',
});

// Create a customer
const newCustomer = await client.customers.create.mutate({
  companyName: 'Acme Corporation',
  contactEmail: 'contact@acme.com',
  status: 'active',
});

// Update a customer
const updated = await client.customers.update.mutate({
  id: newCustomer.id,
  data: {
    contactPhone: '+1-555-0123',
  },
});

// Delete a customer
await client.customers.delete.mutate({
  id: newCustomer.id,
});

Benefits of tRPC Client

  • Full Type Safety: TypeScript types for all requests and responses
  • Auto-completion: IDE support for all endpoints and parameters
  • Type Inference: Automatic type inference for responses
  • Compile-time Errors: Catch errors before runtime
  • Better DX: Improved developer experience

Common Workflows

1. Customer Management

// Create customer
const customer = await client.customers.create.mutate({
  companyName: 'Acme Corp',
  contactEmail: 'billing@acme.com',
});

// Create invoice for customer
const invoice = await client.invoices.create.mutate({
  customerId: customer.id,
  invoiceDate: new Date(),
  dueDate: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000), // 30 days
  lineItems: [
    {
      description: 'Professional Services',
      quantity: 10,
      rate: 150.00,
      amount: 1500.00,
    },
  ],
});

// Record payment
const payment = await client.payments.create.mutate({
  invoiceId: invoice.id,
  customerId: customer.id,
  amount: 1500.00,
  paymentDate: new Date(),
  paymentMethod: 'credit_card',
});

2. Subscription Revenue Recognition

// Create subscription
const subscription = await client.subscriptions.create.mutate({
  customerId: customer.id,
  startDate: new Date(),
  endDate: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000), // 1 year
  billingFrequency: 'monthly',
  amount: 1000.00,
});

// Calculate revenue recognition
const revenue = await client.revenue.calculateRevenue.mutate({
  subscriptionId: subscription.id,
  recognitionMethod: 'straight_line',
});

// Get revenue schedules
const schedules = await client.revenue.getSchedules.query({
  subscriptionId: subscription.id,
});

3. Inventory Management

// Create item
const item = await client.items.create.mutate({
  name: 'Product A',
  sku: 'SKU-001',
  itemType: 'INVENTORY_ITEM',
  unitOfMeasureId: uomId,
  unitPrice: 99.99,
});

// Assign to warehouse
const warehouseItem = await client.warehouses.assignItem.mutate({
  warehouseId: warehouseId,
  itemId: item.id,
  quantity: 100,
});

// Create price list
const priceList = await client.priceLists.create.mutate({
  name: 'Standard Pricing',
  effectiveDate: new Date(),
  items: [
    {
      itemId: item.id,
      price: 89.99,  // Discounted price
    },
  ],
});

Next Steps

Now that you've completed the basics, explore more advanced topics:

  1. Authentication - Learn about secure authentication
  2. API Endpoints - Explore all available endpoints
  3. Object Types - Understand data structures
  4. Interactive API Reference - Test endpoints in your browser
  5. Revenue Recognition Guide - Implement ASC 606 compliance
  6. Multi-Tenant Setup - Configure organizations and subsidiaries

Need Help?

Example Projects

Check out complete example projects:

Best Practices

1. Error Handling

Always handle errors appropriately:

try {
  const customer = await client.customers.get.query({ id: customerId });
} catch (error) {
  if (error.code === 'NOT_FOUND') {
    console.log('Customer not found');
  } else if (error.code === 'UNAUTHORIZED') {
    console.log('Invalid authentication');
  } else {
    console.error('Unexpected error:', error);
  }
}

2. Environment-Specific Configuration

Use different configurations for development and production:

const API_URL = process.env.NODE_ENV === 'production'
  ? 'https://api.glapi.io/api/trpc'
  : 'http://localhost:3031/api/trpc';

const client = createTRPCClient<AppRouter>({
  links: [httpBatchLink({ url: API_URL })],
});

3. Rate Limiting

Implement retry logic with exponential backoff:

async function withRetry<T>(fn: () => Promise<T>, maxRetries = 3): Promise<T> {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      if (error.code === 'TOO_MANY_REQUESTS' && i < maxRetries - 1) {
        await new Promise(resolve => setTimeout(resolve, 1000 * Math.pow(2, i)));
      } else {
        throw error;
      }
    }
  }
  throw new Error('Max retries exceeded');
}

const customers = await withRetry(() => client.customers.list.query());

4. Batch Operations

Use batch operations when creating multiple resources:

const customerPromises = customerData.map(data =>
  client.customers.create.mutate(data)
);

const customers = await Promise.all(customerPromises);

Troubleshooting

Common Issues

401 Unauthorized

  • Verify your API token is correct
  • Check the Authorization header format
  • Ensure token hasn't expired

404 Not Found

  • Verify the resource ID is correct
  • Check you're accessing the correct environment (dev vs prod)
  • Ensure the resource belongs to your organization

429 Too Many Requests

  • Implement rate limiting in your application
  • Use exponential backoff for retries
  • Consider batching requests

500 Internal Server Error

  • Check the API status page
  • Review request payload for invalid data
  • Contact support if issue persists

Happy coding! 🚀