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
- Review error handling guidelines
- Learn about rate limits
- Explore the API Reference