Best Practices
Security and Best Practices
Follow these best practices to build secure, reliable, and efficient integrations with the Tadabase REST API.
Security
1. Protect API Credentials
?? Critical Security Rule
Never expose API credentials in:
- Client-side JavaScript (browser code)
- Public repositories (GitHub, GitLab, etc.)
- Mobile app code
- Browser console logs
- Screenshot or documentation
- Error messages shown to users
2. Use Environment Variables
Store credentials in environment variables, not in code:
// ? Bad: Credentials in code
const headers = {
'X-Tadabase-App-id': '74QY8R4ENB',
'X-Tadabase-App-Key': 'KbQClTItwTVc',
'X-Tadabase-App-Secret': 'wu3AFIDdmNK1dyaorIIPqyZkvG7ssMs4'
};
// ? Good: Use environment variables
const headers = {
'X-Tadabase-App-id': process.env.TADABASE_APP_ID,
'X-Tadabase-App-Key': process.env.TADABASE_APP_KEY,
'X-Tadabase-App-Secret': process.env.TADABASE_APP_SECRET
};
3. Least Privilege Principle
Grant API keys only the permissions they need:
| Use Case | Recommended Permissions |
|---|---|
| Read-only reporting | allow_get only |
| Data import/sync | allow_get, allow_edit |
| Scheduled tasks | allow_task only |
| Full admin access | All permissions (use sparingly) |
4. Rotate Keys Regularly
Generate new API keys periodically:
- Create new API key
- Update all integrations to use new key
- Verify new key works
- Delete old API key
5. Regenerate Compromised Keys Immediately
If an API key is exposed:
- Immediately generate a new key
- Update all integrations
- Delete the compromised key
- Review API logs for unauthorized access
6. Use HTTPS Only
Always use HTTPS endpoints:
// ? Good: HTTPS
https://api.tadabase.io/api/v1/...
// ? Never use HTTP
http://api.tadabase.io/api/v1/...
7. Implement IP Whitelisting (If Available)
If your infrastructure uses static IPs:
- Restrict API access to specific IP addresses
- Use VPN or proxy for consistent IP
- Contact support for IP whitelisting options
8. Separate Keys by Environment
Use different API keys for different environments:
- Development: Separate key for testing
- Staging: Key for pre-production testing
- Production: Key for live environment
Performance Optimization
1. Minimize Field Selection
// ? Bad: Fetches all fields (large response)
GET /api/v1/data-tables/{tableId}/records
// ? Good: Only fetch needed fields
GET /api/v1/data-tables/{tableId}/records?fields=id,name,email
2. Use Pagination Effectively
// ? Bad: Fetches default 100 even if you need 10
GET /api/v1/data-tables/{tableId}/records
// ? Good: Only fetch what you need
GET /api/v1/data-tables/{tableId}/records?limit=10
3. Batch Operations
// ? Bad: 100 individual update requests
for (const id of recordIds) {
await updateRecord(id, { status: 'Active' });
}
// ? Good: 1 batch update request
await batchUpdate({
conditions: [...],
values: [{ field_id: 'status', value: 'Active' }]
});
4. Cache API Responses
class CachedAPI {
constructor() {
this.cache = new Map();
}
async get(key, fetcher, ttl = 300000) {
if (this.cache.has(key)) {
const { data, timestamp } = this.cache.get(key);
if (Date.now() - timestamp getTables(), 300000);
5. Queue Formula Execution for Bulk Operations
POST /api/v1/data-tables/{tableId}/records
Headers:
X-Tadabase-Queue-Equation: 1
// Formulas execute asynchronously, response is faster
6. Use Webhooks Instead of Polling
// ? Bad: Polling every 5 seconds
setInterval(async () => {
const records = await getNewRecords();
processRecords(records);
}, 5000);
// ? Good: Webhook triggered when records change
app.post('/webhook', (req, res) => {
const record = req.body;
processRecord(record);
res.status(200).send('OK');
});
Data Integrity
1. Validate Before Sending
function validateRecord(record) {
const required = ['first_name', 'last_name', 'email'];
const missing = required.filter(field => !record[field]);
if (missing.length > 0) {
throw new Error(`Missing required fields: ${missing.join(', ')}`);
}
if (record.email && !isValidEmail(record.email)) {
throw new Error('Invalid email format');
}
return true;
}
// Validate before API call
validateRecord(newRecord);
await createRecord(newRecord);
2. Check Unique Constraints
async function createRecordSafely(data) {
// Check if email already exists
const existing = await getRecords({
filters: {
condition: "AND",
items: [
{ field_id: "email", operator: "is", val: data.email }
]
}
});
if (existing.items.length > 0) {
// Update existing record instead
return updateRecord(existing.items[0].id, data);
}
// Create new record
return createRecord(data);
}
3. Use Transactions for Multi-Step Operations
async function transferData(fromId, toId, amount) {
try {
// Step 1: Deduct from source
const source = await getRecord(fromId);
if (source.balance
4. Backup Before Bulk Operations
Before large bulk updates or deletes:
- Export affected records
- Test operation on copy/sandbox first
- Perform operation in production
- Verify results
- Keep backup for rollback if needed
Monitoring and Logging
1. Log All API Requests
async function loggedApiRequest(url, options) {
const startTime = Date.now();
try {
const response = await fetch(url, options);
const data = await response.json();
logger.info({
url,
method: options.method || 'GET',
status: response.status,
duration: Date.now() - startTime,
success: data.type === 'success'
});
return data;
} catch (error) {
logger.error({
url,
method: options.method || 'GET',
error: error.message,
duration: Date.now() - startTime
});
throw error;
}
}
2. Monitor Rate Limits
function monitorRateLimits(response) {
const remaining = parseInt(response.headers.get('X-RateLimit-Remaining'));
const limit = parseInt(response.headers.get('X-RateLimit-Limit'));
const percentage = (remaining / limit) * 100;
if (percentage
3. Track Error Rates
class APIMetrics {
constructor() {
this.requests = 0;
this.errors = 0;
this.startTime = Date.now();
}
recordRequest(success) {
this.requests++;
if (!success) this.errors++;
}
getErrorRate() {
return this.requests > 0 ? (this.errors / this.requests) * 100 : 0;
}
getRequestsPerMinute() {
const minutes = (Date.now() - this.startTime) / 60000;
return this.requests / minutes;
}
}
const metrics = new APIMetrics();
// After each request
metrics.recordRequest(response.type === 'success');
// Monitor
setInterval(() => {
console.log({
errorRate: metrics.getErrorRate(),
requestsPerMinute: metrics.getRequestsPerMinute()
});
}, 60000);
4. Set Up Alerts
- Alert when error rate exceeds threshold (e.g., 5%)
- Alert when approaching rate limits
- Alert on authentication failures
- Alert on repeated 500 errors
Development Workflow
1. Test in Sandbox First
Always test in a development/sandbox environment before production:
- Create duplicate app for testing
- Generate separate API keys
- Test all operations thoroughly
- Verify results
- Deploy to production
2. Use API Tester for Exploration
Before writing code:
- Test endpoints in API Tester (
/api) - Verify request/response format
- Export working request as curl or Postman
- Translate to code
3. Version Control Your Integration
- Keep API integration code in version control (Git)
- Document API key configuration in README
- Use
.gitignoreto exclude credentials - Tag releases for production deployments
4. Document Your Integration
Maintain documentation for:
- Which API endpoints are used
- What data is synced and how often
- Error handling procedures
- Rollback procedures
- Contact information for support
5. Code Review API Integrations
Have team members review code for:
- Security issues (exposed credentials)
- Error handling
- Rate limit compliance
- Data validation
- Performance optimization
API Versioning
1. Stay Current
- Use latest API version for new integrations
- Monitor Tadabase release notes for API changes
- Test new API versions in sandbox before migrating
2. Handle Deprecation Gracefully
- Subscribe to API deprecation notices
- Plan migration before deprecation deadline
- Test thoroughly after migration
- Keep rollback plan ready
Common Pitfalls to Avoid
| Pitfall | Impact | Solution |
|---|---|---|
| Hardcoding credentials | Security risk | Use environment variables |
| No error handling | Silent failures | Implement comprehensive error handling |
| Ignoring rate limits | 429 errors, blocked requests | Monitor and implement throttling |
| Fetching all fields | Slow responses | Use fields parameter |
| Individual updates in loop | Many API calls | Use batch operations |
| No validation | 422 errors | Validate before sending |
| Not testing in sandbox | Production issues | Always test first |
| No logging/monitoring | Hard to debug | Implement logging and alerts |
Production Checklist
Before deploying to production:
- ? Credentials stored in environment variables
- ? Error handling implemented
- ? Rate limiting strategy in place
- ? Logging and monitoring configured
- ? Tested in sandbox environment
- ? Data validation implemented
- ? Backup/rollback plan documented
- ? Security review completed
- ? Performance tested with realistic load
- ? Documentation updated
Getting Help
- API Documentation: Complete reference for all endpoints
- API Tester:
/api- Test endpoints interactively - Support: Contact Tadabase support for API questions
- Community Forum: Connect with other developers
- API Logs: Settings ? Logs ? API Logs for debugging
Conclusion
Following these best practices will help you build secure, reliable, and efficient integrations with the Tadabase REST API. Remember:
- Security first: Protect credentials, use least privilege
- Optimize for performance: Cache, batch, minimize data
- Handle errors gracefully: Retry, log, monitor
- Test thoroughly: Sandbox first, production later
- Monitor and maintain: Track metrics, review logs, stay updated
Happy coding! ?
We'd love to hear your feedback.