postkit
Concepts

Rate Limits & Quotas

Understand API rate limits and sending quotas

Postkit uses rate limiting to ensure fair API access and protect infrastructure. Understanding these limits helps you build resilient integrations that handle throttling gracefully.

Rate limits

Every API request is rate-limited per organization. The limits are applied using a sliding window algorithm that tracks requests per second.

EndpointLimit
Most endpoints10 requests/second
Batch email (POST /v1/emails/batch)2 requests/second

When you make an API request, the response includes headers that tell you your current rate limit status:

X-RateLimit-Limit: 10
X-RateLimit-Remaining: 7
X-RateLimit-Reset: 1711900060
  • X-RateLimit-Limit -- The maximum number of requests allowed per second for this endpoint.
  • X-RateLimit-Remaining -- How many requests you have left in the current window.
  • X-RateLimit-Reset -- A Unix timestamp indicating when the rate limit window resets.

These headers are included on every successful response, so you can monitor your usage proactively rather than waiting for a rejection.

Handling rate limit responses

When you exceed the rate limit, the API returns a 429 Too Many Requests response:

{
  "error": {
    "type": "rate_limit_error",
    "message": "Rate limit exceeded. Retry after 1 second.",
    "code": "rate_limit_exceeded"
  }
}

The response also includes a Retry-After header with the number of seconds to wait before retrying:

Retry-After: 1

Exponential backoff

The most reliable way to handle rate limits is exponential backoff with jitter. Instead of retrying immediately or at fixed intervals, increase the wait time between each retry attempt and add a small random delay to prevent thundering herd effects:

  1. First retry: wait 1 second
  2. Second retry: wait 2 seconds
  3. Third retry: wait 4 seconds
  4. Add random jitter (0-500ms) to each wait

Always respect the Retry-After header when present -- it tells you the minimum time to wait. If Retry-After is longer than your calculated backoff, use Retry-After instead.

Sending quotas

Each Postkit plan includes a monthly sending quota that determines how many emails you can send per billing cycle. When you exceed your quota, additional emails are billed as overage at your plan's per-email rate.

Your quota resets at the start of each billing cycle. You can check your current usage and remaining quota in the Postkit dashboard.

Quota limits apply to delivered emails, not API requests. A single API request to the batch endpoint can consume multiple emails from your quota.

Pagination

Postkit uses cursor-based pagination for all list endpoints. Unlike offset-based pagination, cursor pagination provides consistent results even when data changes between page requests -- you will never see duplicated or skipped items.

Parameters

ParameterTypeDescription
limitintegerNumber of items per page. Default: 25, maximum: 100.
starting_afterstringThe id of the last item from the previous page. Returns items created after this one.
ending_beforestringThe id of the first item from the previous page. Returns items created before this one.

Response format

List endpoints return a data array and a has_more boolean:

{
  "data": [
    { "id": "em_a1b2c3d4e5", "status": "delivered", "...": "..." },
    { "id": "em_f6g7h8i9j0", "status": "queued", "...": "..." }
  ],
  "has_more": true
}

When has_more is true, there are additional items to fetch. Use the id of the last item in data as the starting_after parameter for the next request:

curl https://api.postkit.eu/v1/emails?limit=25&starting_after=em_f6g7h8i9j0 \
  -H "Authorization: Bearer pk_live_abc123..."

Why cursor-based?

Offset-based pagination (?page=2&per_page=25) breaks down when data is being created or deleted between page requests. If a new email is sent while you are paginating, offset pagination might show the same email twice or skip one entirely.

Cursor pagination avoids this by anchoring each page request to a specific item rather than a numeric position. The result is a stable, predictable traversal of your data regardless of concurrent changes.

What's next?

  • Idempotency -- safely retry API requests without sending duplicates
  • Error Handling -- understand all API error types and how to handle them