Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/DUVAN100/saludya-api/llms.txt

Use this file to discover all available pages before exploring further.

Overview

SaludYa API implements rate limiting to ensure fair usage and maintain service quality for all users. Rate limits prevent abuse and help maintain optimal performance for medical appointment management operations.
Rate limits are applied per API key and reset at the end of each time window.

Rate Limit Tiers

Different usage tiers have different rate limits:
TierRequests per 15 minutesRequests per hourRequests per day
Free1003001,000
Basic5001,50010,000
Professional2,0006,00050,000
EnterpriseCustomCustomCustom
Exceeding rate limits will result in 429 Too Many Requests responses. Your application should handle these gracefully.

Rate Limit Headers

Every API response includes rate limit information in the headers:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 85
X-RateLimit-Reset: 1709719200
X-RateLimit-Window: 900
HeaderDescription
X-RateLimit-LimitMaximum requests allowed in the current window
X-RateLimit-RemainingNumber of requests remaining in the current window
X-RateLimit-ResetUnix timestamp when the rate limit resets
X-RateLimit-WindowLength of the rate limit window in seconds

Handling Rate Limits

Checking Rate Limit Status

Monitor rate limit headers to track your usage:
const makeRequest = async (url) => {
  const response = await fetch(url, {
    headers: {
      'Authorization': `Bearer ${token}`
    }
  });

  // Check rate limit headers
  const limit = response.headers.get('X-RateLimit-Limit');
  const remaining = response.headers.get('X-RateLimit-Remaining');
  const reset = response.headers.get('X-RateLimit-Reset');

  console.log(`Rate limit: ${remaining}/${limit} requests remaining`);
  console.log(`Resets at: ${new Date(reset * 1000).toISOString()}`);

  if (response.status === 429) {
    const retryAfter = response.headers.get('Retry-After');
    throw new Error(`Rate limit exceeded. Retry after ${retryAfter} seconds`);
  }

  return response.json();
};

Implementing Retry Logic

Implement exponential backoff when encountering rate limits:
const makeRequestWithRetry = async (url, maxRetries = 3) => {
  let retries = 0;

  while (retries < maxRetries) {
    try {
      const response = await fetch(url, {
        headers: { 'Authorization': `Bearer ${token}` }
      });

      if (response.status === 429) {
        const retryAfter = parseInt(
          response.headers.get('Retry-After') || '60'
        );
        
        console.log(`Rate limited. Waiting ${retryAfter}s before retry...`);
        await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
        
        retries++;
        continue;
      }

      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
      }

      return response.json();
    } catch (error) {
      if (retries >= maxRetries - 1) throw error;
      
      // Exponential backoff
      const waitTime = Math.pow(2, retries) * 1000;
      console.log(`Error occurred. Retrying in ${waitTime}ms...`);
      await new Promise(resolve => setTimeout(resolve, waitTime));
      
      retries++;
    }
  }

  throw new Error('Max retries exceeded');
};
Always respect the Retry-After header value when implementing retry logic. This ensures you don’t waste requests during rate limit periods.

Rate Limit Response

When you exceed the rate limit, you’ll receive a 429 response:
{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Please try again later.",
    "retryAfter": 45,
    "limit": 100,
    "window": "15 minutes"
  }
}

Response Headers

HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1709719200
Retry-After: 45

Best Practices

1. Cache Responses

Reduce API calls by caching frequently accessed data:
class APIClient {
  constructor() {
    this.cache = new Map();
    this.cacheDuration = 5 * 60 * 1000; // 5 minutes
  }

  async getWithCache(endpoint) {
    const cached = this.cache.get(endpoint);
    
    if (cached && Date.now() - cached.timestamp < this.cacheDuration) {
      console.log('Returning cached data');
      return cached.data;
    }

    const data = await this.makeRequest(endpoint);
    
    this.cache.set(endpoint, {
      data,
      timestamp: Date.now()
    });

    return data;
  }

  async makeRequest(endpoint) {
    const response = await fetch(`https://api.saludya.com/v1${endpoint}`, {
      headers: { 'Authorization': `Bearer ${token}` }
    });
    
    return response.json();
  }
}

2. Use Batch Operations

When creating or updating multiple resources, use batch endpoints:
// Instead of multiple single requests:
// ❌ Don't do this
for (const appointment of appointments) {
  await createAppointment(appointment);
}

// ✅ Use batch endpoint
await fetch('https://api.saludya.com/v1/appointments/batch', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ appointments })
});

3. Implement Request Queuing

Queue requests to stay within rate limits:
class RateLimitedQueue {
  constructor(maxRequestsPerWindow = 100, windowMs = 15 * 60 * 1000) {
    this.queue = [];
    this.processing = false;
    this.maxRequests = maxRequestsPerWindow;
    this.windowMs = windowMs;
    this.requestCount = 0;
    this.windowStart = Date.now();
  }

  async add(requestFn) {
    return new Promise((resolve, reject) => {
      this.queue.push({ requestFn, resolve, reject });
      this.process();
    });
  }

  async process() {
    if (this.processing || this.queue.length === 0) return;
    
    this.processing = true;

    while (this.queue.length > 0) {
      // Reset counter if window has passed
      if (Date.now() - this.windowStart >= this.windowMs) {
        this.requestCount = 0;
        this.windowStart = Date.now();
      }

      // Wait if limit reached
      if (this.requestCount >= this.maxRequests) {
        const waitTime = this.windowMs - (Date.now() - this.windowStart);
        console.log(`Rate limit reached. Waiting ${waitTime}ms...`);
        await new Promise(resolve => setTimeout(resolve, waitTime));
        this.requestCount = 0;
        this.windowStart = Date.now();
      }

      const { requestFn, resolve, reject } = this.queue.shift();
      
      try {
        const result = await requestFn();
        this.requestCount++;
        resolve(result);
      } catch (error) {
        reject(error);
      }

      // Small delay between requests
      await new Promise(resolve => setTimeout(resolve, 100));
    }

    this.processing = false;
  }
}

// Usage
const queue = new RateLimitedQueue(100, 15 * 60 * 1000);

const fetchAppointment = (id) => {
  return queue.add(() => 
    fetch(`https://api.saludya.com/v1/appointments/${id}`, {
      headers: { 'Authorization': `Bearer ${token}` }
    }).then(r => r.json())
  );
};

4. Monitor Usage

Track your API usage to prevent hitting limits:
class UsageMonitor {
  constructor() {
    this.requests = [];
  }

  recordRequest(remaining, limit, resetTime) {
    this.requests.push({
      timestamp: Date.now(),
      remaining,
      limit,
      resetTime
    });

    // Alert if usage is high
    const usagePercent = ((limit - remaining) / limit) * 100;
    
    if (usagePercent > 80) {
      console.warn(
        `⚠️ High API usage: ${usagePercent.toFixed(1)}% of rate limit used`
      );
    }
  }

  getStats() {
    const now = Date.now();
    const last15Min = this.requests.filter(
      r => now - r.timestamp < 15 * 60 * 1000
    );

    return {
      requestsLast15Min: last15Min.length,
      averageRemaining: last15Min.reduce(
        (sum, r) => sum + r.remaining, 0
      ) / last15Min.length
    };
  }
}

5. Use Webhooks for Real-time Updates

Instead of polling for changes, use webhooks to receive real-time notifications:
// ❌ Don't poll repeatedly
setInterval(async () => {
  const appointments = await fetchAppointments();
  checkForUpdates(appointments);
}, 30000); // This wastes rate limit!

// ✅ Use webhooks instead
// Configure webhook endpoint to receive appointment updates
// See /guides/webhooks for setup instructions
Avoid polling the API frequently. Use webhooks for real-time updates to conserve your rate limit.

Endpoint-Specific Limits

Some endpoints have additional rate limits:
EndpointAdditional LimitReason
POST /auth/login5 per minuteSecurity - prevent brute force
POST /auth/reset-password3 per hourSecurity - prevent abuse
POST /appointments/batch10 per hourResource protection
GET /reports/*20 per hourComputational cost

Increasing Rate Limits

If your application requires higher rate limits:
1

Assess your needs

Document your expected API usage patterns and peak request volumes.
2

Optimize your implementation

Ensure you’re following all best practices:
  • Caching responses
  • Using batch endpoints
  • Implementing request queuing
  • Using webhooks instead of polling
3

Upgrade your plan

Consider upgrading to a higher tier plan that better suits your needs.Contact sales at sales@saludya.com or visit the pricing page.
4

Enterprise solutions

For custom rate limits and SLA guarantees, contact our enterprise team for a tailored solution.

Testing Rate Limits

When developing, you can test rate limit handling:
# Make rapid requests to trigger rate limiting
for i in {1..150}; do
  curl -X GET 'https://api.saludya.com/v1/appointments' \
    -H "Authorization: Bearer $TOKEN" \
    -w "\nStatus: %{http_code}\n"
  sleep 0.1
done
Use a development or sandbox environment for rate limit testing to avoid impacting your production quota.

Rate Limit FAQs

Rate limits are applied per API key. If you need to isolate rate limits for different applications, create separate API keys for each.
When the rate limit window resets, your quota is fully restored. Any properly queued requests will be processed in order.
Most endpoints share the same rate limit, but authentication and resource-intensive endpoints have additional restrictions. See the endpoint-specific limits section above.
Yes, contact support at support@saludya.com with details about your use case and duration needed. Temporary increases are evaluated on a case-by-case basis.
Yes, all requests (successful or failed) count toward your rate limit, except for 500-level server errors which do not count against your quota.

Next Steps

Authentication

Learn about securing your API requests

API Reference

Explore all available endpoints

Making Requests

Learn about pagination and filtering

Error Handling

Handle API errors gracefully

Build docs developers (and LLMs) love