Guides & Concepts
Best Practices

Best Practices

Follow these best practices to get the most out of Mumin API.

Authentication

Secure Your API Keys

⚠️

Never commit API keys to version control or expose them in client-side code.

✅ Good:

// Use environment variables
const apiKey = process.env.MUMIN_API_KEY

❌ Bad:

// Don't hardcode keys
const apiKey = 'sk_mumin_abc123...'

Rotate Keys Regularly

Rotate your API keys every 90 days for security.

Rate Limiting

Implement Exponential Backoff

javascript✨ Live Editor

Monitor Rate Limits

const response = await fetch('...')
const remaining = response.headers.get('X-RateLimit-Remaining')
const reset = response.headers.get('X-RateLimit-Reset')
 
if (parseInt(remaining) < 10) {
  console.warn('Rate limit almost exceeded!')
}

Caching

Cache Responses

API responses are cached for 24 hours. Implement your own caching for better performance.

const cache = new Map()
 
async function getCachedHadith(id) {
  if (cache.has(id)) {
    return cache.get(id)
  }
  
  const hadith = await fetchHadith(id)
  cache.set(id, hadith)
  
  // Expire after 1 hour
  setTimeout(() => cache.delete(id), 3600000)
  
  return hadith
}

Error Handling

Handle All Error Cases

try {
  const hadith = await client.hadiths.get(id)
} catch (error) {
  if (error.code === 'NOT_FOUND') {
    // Handle missing hadith
  } else if (error.code === 'RATE_LIMIT_EXCEEDED') {
    // Wait and retry
  } else if (error.code === 'BALANCE_DEPLETED') {
    // Notify user to top up
  } else {
    // Log unexpected errors
    console.error('Unexpected error:', error)
  }
}

Performance

Use Pagination

Don't fetch all hadiths at once. Use pagination:

async function getAllHadiths() {
  const limit = 100
  let offset = 0
  const allHadiths = []
  
  while (true) {
    const response = await client.hadiths.list({ limit, offset })
    allHadiths.push(...response.data)
    
    if (response.data.length < limit) break
    offset += limit
  }
  
  return allHadiths
}

Request Only Needed Languages

// ✅ Good - only request needed languages
const hadith = await client.hadiths.get(1, { lang: 'en' })
 
// ❌ Bad - requesting all languages
const hadith = await client.hadiths.get(1, { lang: 'ar,en,ru,uz' })

Security

Use HTTPS Only

Always use HTTPS in production:

const API_URL = process.env.NODE_ENV === 'production'
  ? 'https://api.mumin.ink/v1'
  : 'http://localhost:3000/v1'

Validate Input

function validateHadithId(id) {
  const numId = parseInt(id)
  if (isNaN(numId) || numId < 1 || numId > 7563) {
    throw new Error('Invalid hadith ID')
  }
  return numId
}

Monitoring

Log Request IDs

Always log requestId for debugging:

try {
  const hadith = await client.hadiths.get(id)
} catch (error) {
  console.error('Request failed:', {
    requestId: error.requestId,
    error: error.message
  })
}

Track Usage

Monitor your API usage:

let requestCount = 0
 
async function trackRequest(fn) {
  requestCount++
  console.log(`Total requests: ${requestCount}`)
  return await fn()
}

Cost Optimization

Batch Requests

Instead of making multiple requests, batch them:

// ✅ Good - batch requests
const hadiths = await Promise.all([
  client.hadiths.get(1),
  client.hadiths.get(2),
  client.hadiths.get(3)
])
 
// ❌ Bad - sequential requests
const h1 = await client.hadiths.get(1)
const h2 = await client.hadiths.get(2)
const h3 = await client.hadiths.get(3)

Use Search Wisely

Search is more expensive than direct access:

// ✅ Good - if you know the ID
const hadith = await client.hadiths.get(1)
 
// ❌ Bad - using search when ID is known
const results = await client.hadiths.search('hadith 1')