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.