Skip to main content

Best Practices

Follow these best practices to build robust integrations with the TempsReel API.

General Guidelines

1. Use HTTPS Always

Always use the correct base URL for your environment. For pre-production, use HTTP.

// ✅ Good
const apiUrl = 'http://tempsreel-pre.connect.tickandlive.com';

// ❌ Bad - Use the correct pre-production URL
const apiUrl = 'http://api.tickandlive.com';

2. Set Appropriate Timeouts

Set reasonable timeouts to avoid hanging requests:

const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 30000); // 30s timeout

try {
const response = await fetch(url, {
signal: controller.signal,
headers: { 'x-tenant': tenantId }
});
clearTimeout(timeoutId);
} catch (error) {
if (error.name === 'AbortError') {
console.error('Request timeout');
}
}

3. Validate Input Before Sending

Validate data locally before making API calls:

function validateDateRange(dateFrom, dateTo) {
if (!dateFrom || !dateTo) {
throw new Error('Both dates are required');
}

const from = new Date(dateFrom);
const to = new Date(dateTo);

if (from > to) {
throw new Error('dateFrom must be less than dateTo');
}

return true;
}

4. Handle Network Errors

Network errors can occur. Implement proper error handling:

async function apiCall(url, options) {
try {
const response = await fetch(url, options);
return await response.json();
} catch (error) {
if (error instanceof TypeError) {
// Network error
console.error('Network error:', error.message);
throw new Error('Unable to connect to API. Please check your connection.');
}
throw error;
}
}

Performance Optimization

1. Implement Caching

Cache responses when appropriate:

const cache = new Map();
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes

async function getCachedData(key, fetchFn) {
const cached = cache.get(key);

if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
return cached.data;
}

const data = await fetchFn();
cache.set(key, { data, timestamp: Date.now() });
return data;
}

2. Use Pagination

When endpoints support pagination, use it to fetch data in chunks:

async function* fetchAllPages(baseUrl, headers) {
let page = 1;
let hasMore = true;

while (hasMore) {
const response = await fetch(`${baseUrl}?page=${page}`, { headers });
const data = await response.json();

yield* data.items;

hasMore = data.hasMore;
page++;
}
}

3. Batch Requests

Combine multiple requests when possible:

// Instead of:
const event1 = await fetch('/api/catalog/events/1');
const event2 = await fetch('/api/catalog/events/2');
const event3 = await fetch('/api/catalog/events/3');

// Use:
const events = await fetch('/api/catalog/events?eventIds=1,2,3');

4. Use Compression

Enable gzip compression if your HTTP client supports it:

const response = await fetch(url, {
headers: {
'Accept-Encoding': 'gzip',
'x-tenant': tenantId
}
});

Security

1. Never Expose Credentials

Never commit tenant IDs or API keys to version control:

// ✅ Good - Use environment variables
const tenantId = process.env.TENANT_ID;

// ❌ Bad - Hardcoded
const tenantId = 'your-tenant-id';

2. Use Environment-Specific Configuration

const config = {
preproduction: {
apiUrl: 'http://tempsreel-pre.connect.tickandlive.com',
tenantId: process.env.TENANT_ID
}
};

const apiConfig = config.preproduction;

3. Validate Responses

Always validate API responses before using them:

function validateEventResponse(data) {
if (!data || !Array.isArray(data.events)) {
throw new Error('Invalid response format');
}

return data.events.filter(event =>
event.id && event.name && event.startDate
);
}

Error Handling

1. Implement Retry Logic

Retry transient errors with exponential backoff:

async function fetchWithRetry(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url, options);
if (response.ok) return response;

if (response.status >= 500 && i < maxRetries - 1) {
await sleep(Math.pow(2, i) * 1000);
continue;
}

throw new Error(`Request failed: ${response.status}`);
} catch (error) {
if (i === maxRetries - 1) throw error;
}
}
}

2. Log Errors Appropriately

Log errors with context but avoid logging sensitive data:

logger.error('API request failed', {
url,
status: error.status,
traceId: error.traceId,
// Don't log tenant ID or sensitive data
});

Code Organization

1. Create an API Client Class

Encapsulate API logic in a reusable client:

class TempsReelClient {
constructor(tenantId, baseUrl = 'http://tempsreel-pre.connect.tickandlive.com') {
this.tenantId = tenantId;
this.baseUrl = baseUrl;
}

async getEvents(dateFrom, dateTo) {
const url = `${this.baseUrl}/api/catalog/events`;
const params = new URLSearchParams({ dateFrom, dateTo });

return this.request(`${url}?${params}`);
}

async request(url, options = {}) {
const response = await fetch(url, {
...options,
headers: {
'x-tenant': this.tenantId,
'Accept': 'application/json',
...options.headers
}
});

if (!response.ok) {
const error = await response.json();
throw new ApiError(error.detail, response.status);
}

return response.json();
}
}

2. Use TypeScript for Type Safety

Define types for API responses:

interface CatalogEvent {
id: number;
name: string;
venueId: number;
startDate: string;
endDate: string;
}

interface CatalogEventsResponse {
events: CatalogEvent[];
}

Testing

1. Test with Pre-production First

Always test integrations in the pre-production environment:

const client = new TempsReelClient(
process.env.TENANT_ID,
'http://tempsreel-pre.connect.tickandlive.com'
);

2. Mock API Responses in Tests

Mock API responses for unit tests:

jest.mock('./api-client', () => ({
TempsReelClient: jest.fn().mockImplementation(() => ({
getEvents: jest.fn().mockResolvedValue({
events: [{ id: 1, name: 'Test Event' }]
})
}))
}));

Next Steps