Back to User Guide

Code Examples

Practical examples for common API tasks.

Setup

Node.js

const axios = require('axios');

const relay = axios.create({
  baseURL: 'https://your-domain.com/api/v1',
  headers: {
    'Authorization': `Bearer ${process.env.RELAY_API_KEY}`,
    'Content-Type': 'application/json'
  }
});

Python

import requests
import os

BASE_URL = 'https://your-domain.com/api/v1'
HEADERS = {
    'Authorization': f'Bearer {os.environ["RELAY_API_KEY"]}',
    'Content-Type': 'application/json'
}

Working with Tickets

Create a Ticket

Node.js:

async function createTicket(subject, description, customerEmail) {
  const response = await relay.post('/tickets', {
    subject,
    description,
    customer_email: customerEmail,
    priority: 'medium'
  });

  return response.data.data;
}

// Usage
const ticket = await createTicket(
  'Need help with order',
  'My order #12345 hasnt arrived',
  'customer@example.com'
);
console.log('Created ticket:', ticket.id);

Python:

def create_ticket(subject, description, customer_email):
    response = requests.post(
        f'{BASE_URL}/tickets',
        headers=HEADERS,
        json={
            'subject': subject,
            'description': description,
            'customer_email': customer_email,
            'priority': 'medium'
        }
    )
    return response.json()['data']

# Usage
ticket = create_ticket(
    'Need help with order',
    'My order #12345 hasnt arrived',
    'customer@example.com'
)
print(f"Created ticket: {ticket['id']}")

List Open Tickets

Node.js:

async function getOpenTickets() {
  const response = await relay.get('/tickets', {
    params: {
      status: 'open',
      limit: 100
    }
  });

  return response.data.data;
}

// Usage
const tickets = await getOpenTickets();
console.log(`Found ${tickets.length} open tickets`);

Python:

def get_open_tickets():
    response = requests.get(
        f'{BASE_URL}/tickets',
        headers=HEADERS,
        params={'status': 'open', 'limit': 100}
    )
    return response.json()['data']

# Usage
tickets = get_open_tickets()
print(f"Found {len(tickets)} open tickets")

Update Ticket Status

Node.js:

async function resolveTicket(ticketId) {
  const response = await relay.patch(`/tickets/${ticketId}`, {
    status: 'resolved'
  });

  return response.data.data;
}

// Usage
await resolveTicket('tkt_123');

Python:

def resolve_ticket(ticket_id):
    response = requests.patch(
        f'{BASE_URL}/tickets/{ticket_id}',
        headers=HEADERS,
        json={'status': 'resolved'}
    )
    return response.json()['data']

# Usage
resolve_ticket('tkt_123')

Working with Conversations

Send a Reply

Node.js:

async function sendReply(ticketId, message) {
  const response = await relay.post('/conversations', {
    ticket_id: ticketId,
    content: message,
    type: 'reply',
    internal: false
  });

  return response.data.data;
}

// Usage
await sendReply('tkt_123', 'Thank you for contacting us. Ive looked into your order and it should arrive tomorrow.');

Add Internal Note

Node.js:

async function addNote(ticketId, note) {
  const response = await relay.post('/conversations', {
    ticket_id: ticketId,
    content: note,
    type: 'note',
    internal: true
  });

  return response.data.data;
}

// Usage
await addNote('tkt_123', 'Customer called, very frustrated. Handle with care.');

Working with Customers

Find or Create Customer

Node.js:

async function findOrCreateCustomer(email, name) {
  // Try to find existing customer
  const searchResponse = await relay.get('/customers', {
    params: { email }
  });

  if (searchResponse.data.data.length > 0) {
    return searchResponse.data.data[0];
  }

  // Create new customer
  const createResponse = await relay.post('/customers', {
    email,
    name
  });

  return createResponse.data.data;
}

// Usage
const customer = await findOrCreateCustomer(
  'new@example.com',
  'New Customer'
);

Get Customer Tickets

Node.js:

async function getCustomerTickets(customerId) {
  const response = await relay.get('/tickets', {
    params: {
      customer_id: customerId,
      limit: 50
    }
  });

  return response.data.data;
}

Webhook Handler

Express.js

const express = require('express');
const crypto = require('crypto');

const app = express();

// Need raw body for signature verification
app.use('/webhook', express.raw({ type: 'application/json' }));

function verifySignature(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  return `sha256=${expected}` === signature;
}

app.post('/webhook', (req, res) => {
  const signature = req.headers['x-relay-signature'];

  if (!verifySignature(req.body, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }

  const event = JSON.parse(req.body);

  // Process event
  switch (event.event) {
    case 'ticket.created':
      handleNewTicket(event.data.ticket);
      break;

    case 'message.customer_reply':
      handleCustomerReply(event.data.message, event.data.ticket);
      break;

    case 'sla.breached':
      handleSLABreach(event.data.ticket);
      break;
  }

  res.status(200).send('OK');
});

function handleNewTicket(ticket) {
  console.log('New ticket:', ticket.id, ticket.subject);
  // Add your logic here
}

function handleCustomerReply(message, ticket) {
  console.log('Customer replied to:', ticket.id);
  // Add your logic here
}

function handleSLABreach(ticket) {
  console.log('SLA breached for:', ticket.id);
  // Alert team, escalate, etc.
}

app.listen(3000);

Flask (Python)

from flask import Flask, request
import hmac
import hashlib
import json
import os

app = Flask(__name__)

def verify_signature(payload, signature, secret):
    expected = hmac.new(
        secret.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()
    return f"sha256={expected}" == signature

@app.route('/webhook', methods=['POST'])
def webhook():
    signature = request.headers.get('X-Relay-Signature')
    secret = os.environ['WEBHOOK_SECRET']

    if not verify_signature(request.data, signature, secret):
        return 'Invalid signature', 401

    event = request.json

    if event['event'] == 'ticket.created':
        handle_new_ticket(event['data']['ticket'])
    elif event['event'] == 'message.customer_reply':
        handle_customer_reply(event['data']['message'])

    return 'OK', 200

def handle_new_ticket(ticket):
    print(f"New ticket: {ticket['id']} - {ticket['subject']}")

def handle_customer_reply(message):
    print(f"Customer replied: {message['body'][:100]}")

if __name__ == '__main__':
    app.run(port=3000)

Bulk Operations

Bulk Update Tickets

Node.js:

async function bulkUpdateTickets(ticketIds, updates) {
  const promises = ticketIds.map(id =>
    relay.patch(`/tickets/${id}`, updates)
  );

  // Process in batches to respect rate limits
  const results = [];
  const batchSize = 10;

  for (let i = 0; i < promises.length; i += batchSize) {
    const batch = promises.slice(i, i + batchSize);
    const batchResults = await Promise.all(batch);
    results.push(...batchResults);

    // Wait between batches
    if (i + batchSize < promises.length) {
      await new Promise(resolve => setTimeout(resolve, 1000));
    }
  }

  return results;
}

// Usage: Assign multiple tickets
await bulkUpdateTickets(
  ['tkt_1', 'tkt_2', 'tkt_3'],
  { assignee_id: 'user_123' }
);

Sync with External CRM

// Sync customers from external CRM
async function syncCustomersFromCRM(crmCustomers) {
  for (const crmCustomer of crmCustomers) {
    // Find or create in Relay
    let customer;

    try {
      const search = await relay.get('/customers', {
        params: { email: crmCustomer.email }
      });

      if (search.data.data.length > 0) {
        // Update existing
        customer = await relay.patch(
          `/customers/${search.data.data[0].id}`,
          {
            name: crmCustomer.name,
            phone: crmCustomer.phone,
            custom_fields: {
              crm_id: crmCustomer.id,
              account_type: crmCustomer.type
            }
          }
        );
      } else {
        // Create new
        customer = await relay.post('/customers', {
          email: crmCustomer.email,
          name: crmCustomer.name,
          phone: crmCustomer.phone,
          custom_fields: {
            crm_id: crmCustomer.id,
            account_type: crmCustomer.type
          }
        });
      }

      console.log(`Synced: ${crmCustomer.email}`);
    } catch (error) {
      console.error(`Failed to sync ${crmCustomer.email}:`, error.message);
    }

    // Rate limit protection
    await new Promise(resolve => setTimeout(resolve, 100));
  }
}

Error Handling

async function safeApiCall(fn) {
  try {
    return await fn();
  } catch (error) {
    if (error.response) {
      const { status, data } = error.response;

      switch (status) {
        case 401:
          throw new Error('Invalid API key');
        case 403:
          throw new Error('Permission denied');
        case 404:
          throw new Error('Resource not found');
        case 429:
          // Wait and retry
          const retryAfter = error.response.headers['retry-after'] || 60;
          await new Promise(r => setTimeout(r, retryAfter * 1000));
          return safeApiCall(fn);
        default:
          throw new Error(data.error?.message || 'API error');
      }
    }
    throw error;
  }
}

// Usage
const tickets = await safeApiCall(() => relay.get('/tickets'));

← REST API | Back to API Overview