emcognito
Back to Blog

Two Different 429s on Emcognito's Alias API: Burst Limit vs Daily Cap

September 30, 2026

Updated

email alias apirate limiting429 too many requestsretry-after headerdeveloper apiemail aliasesapi integration

Keep your real inbox private.

Unlimited aliases, free. No credit card, passwordless sign-in.

Create a free alias →

When you hit an email alias API rate limit 429 on Emcognito, your request failed for one of two distinct reasons: you exceeded the per-key API burst limit of 60 calls per minute, or you hit the daily alias-creation quota. Disambiguating between them takes under a second by inspecting a single response header, allowing your code to either sleep briefly or park new account jobs until the midnight UTC reset.

Which 429 Did You Hit? The Two Limits Behind One Status Code

HTTP 429 Too Many Requests responses returned by POST https://api.emcognito.com/v1/aliases feature a bare JSON object formatted as {"message": "..."} in the body. The payload does not include structured error codes or custom nested objects. Parsing human-readable message text in application logic is brittle, but inspecting the HTTP response headers provides an immediate, deterministic answer. Source: Emcognito source.

Two distinct throttling mechanisms govern the developer alias API:

  • Limit A: The Per-Key Burst Limit. The rate-limiting infrastructure meters traffic at a burst limit of 60 calls per minute per API key. This rate limit applies across all calls to both GET /v1/aliases and POST /v1/aliases. When triggered, the gateway returns an HTTP 429 with a Retry-After header specifying the exact integer seconds to pause.
  • Limit B: The Daily Alias-Creation Cap. This limit is enforced directly within application logic. Paid accounts on Plus can create up to 50 aliases per day through the API, while Pro accounts can create up to 200 per day. This quota meters only creation via POST /v1/aliases. When exhausted, the server returns an HTTP 429 without a Retry-After header, resetting cleanly at 00:00 UTC.

POST /v1/aliases returns HTTP 200 with the new alias under "alias". A refusal from the per-key burst limit carries a Retry-After header giving the whole seconds to wait; the alias-creation cap returns its refusal without one, and that cap clears at midnight UTC. Emcognito sends no X-RateLimit-* headers on either. The current burst and cap figures are on the developer reference.

Because there are no rate-limit headers tracking remaining calls on successful responses, your client cannot inspect remaining headroom on a 200 OK. As outlined in the IETF HTTPAPI Working Group draft on RateLimit header fields, standardized rate-limit headers are an evolving specification rather than a universal requirement across REST services. Emcognito does not emit draft headers or legacy variants. You must track consumption internally or branch strictly on the presence of the Retry-After header when an error occurs.

Your immediate decision rule for handling an email alias API rate limit 429 is straightforward:

  1. If Retry-After exists, read the integer, wait that many seconds, and replay the request.
  2. If Retry-After is missing, cease creation requests immediately; the daily cap is spent until 00:00 UTC.

Reading Retry-After Without Guessing

In the Emcognito API, the Retry-After header appears on exactly two responses: the burst-limit 429 and the rare rate-limit 503 Service Unavailable. It never appears on a successful 200 response, and it never appears on a daily-cap 429.

The rate limiter calculates the burst window conservatively. When you exceed 60 requests within a rolling 60-second window, the limiter returns the full window duration in whole seconds rather than a fractional slice. In a verified live test on /v1/aliases on September 20, 2026, firing a 61st request within a single minute returned an HTTP 429 with retry-after: 60. The server errs on the side of safety: honoring the integer guarantees your next call lands after the bucket clears, avoiding immediate re-throttling at the cost of waiting up to the full minute window.

According to the MDN Web Docs specification for Retry-After, compliant HTTP clients must treat the header value as authoritative. If you invent backoff logic that ignores this header, you risk spamming the endpoint and triggering cascading connection drops.

Below is a minimal Node.js implementation illustrating how to parse this header reliably:

async function handleAliasRequest(requestFn) {
  const response = await requestFn();

if (response.status === 429) { const retryAfterHeader = response.headers.get('retry-after');

if (retryAfterHeader !== null) {
  const waitSeconds = parseInt(retryAfterHeader, 10);
  const sleepMs = (!isNaN(waitSeconds) ? waitSeconds : 60) * 1000;
  console.warn(`Burst limit hit. Waiting ${sleepMs}ms before retrying.`);
  await new Promise((resolve) => setTimeout(resolve, sleepMs));
  return requestFn(); // Retry once burst window expires
}

// No Retry-After header means the daily alias creation cap was reached
throw new Error('Daily creation cap exhausted. Pausing until 00:00 UTC.');

}

return response; }

Avoid branching your error handling on strings found in response.json().message. Human-readable message strings may be refined over time, whereas the presence or absence of the Retry-After header represents a stable transport contract between the gateway and your client.

Why the Daily Cap Is the One That Actually Breaks Your Pipeline

Tripping the 60 call-per-minute API burst limit pauses your pipeline for sixty seconds. In contrast, exhausting your daily creation quota halts programmatic address provisioning for hours. Emcognito evaluates daily creation allowances strictly against calendar days in Coordinated Universal Time (UTC), resetting at 00:00:00 UTC rather than across a rolling 24-hour window.

This daily cap only meters POST /v1/aliases. Read operations against GET /v1/aliases do not count toward your daily creation allowance; the daily cap applies strictly to POST /v1/aliases. If your automated worker exhausts its creation quota at 14:00 UTC, audit jobs, reconciliation tasks, and identity tracking routines running against GET /v1/aliases continue functioning without disruption, provided they stay within the 60 calls-per-minute burst envelope.

This UTC alignment provides a predictable scheduling mechanism for batch automation. If a heavy provisioning job begins at 23:50 UTC, it draws down the current day's quota. Ten minutes later, at 00:00 UTC, the application counters reset, immediately granting a fresh daily allocation. If you run batched user-provisioning jobs, scheduling them across the 00:00 UTC boundary allows high-volume runs to clear without queuing work into the next business day.

Do not confuse developer API quotas with web dashboard usage. Programmatic creation via the API is a distinct capability available on paid plans, metered at 50 per day on Plus and 200 per day on Pro. Upgrading between tiers directly alters this programmatic ceiling, which you can review on the pricing page.

A Retry Loop That Respects Both Limits

A resilient integration must treat transient network noise, burst saturation, and daily quota depletion through distinct handling phases. Multi-tier throttling systems commonly separate immediate capacity spikes from aggregate sustained usage. As outlined in the Amazon API Gateway Request Throttling Guide, distinguishing burst limits from sustained quotas prevents transient spikes from corrupting long-term queuing architectures.

To safely handle an email alias API rate limit 429 without dropping tasks or generating duplicate aliases, your client should follow four concrete rules:

  1. Branch on Header Presence First. When an HTTP 429 is encountered, inspect Retry-After. If present, delay execution by the specified seconds and replay. If absent, abandon retries for that request immediately and defer the job until 00:00 UTC.
  2. Enforce Local Client-Side Rate Limiting. Avoid relying on HTTP 429 responses as primary flow control. Proactively shaping outbound requests with a client-side token bucket or leaky bucket algorithm capped at 50 to 55 requests per minute prevents unneeded round-trip latency. Keeping client concurrency slightly below the 60 calls/minute limit leaves necessary headroom for administrative checks or manual lookups.
  3. Bound Exponential Backoff to Infrastructure Faults. When the API returns an HTTP 503 Service Unavailable, the rate limiter is under load and will also include a Retry-After header. In this specific scenario, as recommended by the Google Cloud API Design Guide on error handling, apply bounded exponential backoff with jitter, honoring the Retry-After duration as the base floor for your backoff calculation.
  4. Ensure Local Request Idempotency. The Emcognito API does not use idempotency tokens. If your application drops a connection after sending a payload, the alias might have been created before the network disconnected. Before retrying a failed transaction, query GET /v1/aliases filtered or matched against your internal records (using the label or source values) to confirm the address was not already minted.

When an alias is created successfully, POST /v1/aliases returns an HTTP 200 status code, not an HTTP 201 Created. Looking strictly for HTTP 201 will cause your retry handler to flag valid aliases as failed attempts, triggering unneeded replays.

# Recommended production pattern in Python
import time
import requests
from datetime import datetime, timezone

BASE_URL = "https://api.emcognito.com/v1" API_KEY = "emk_your_key"

def create_alias_with_backoff(payload, max_burst_retries=3): headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json" }

retries = 0
while retries < max_burst_retries:
    response = requests.post(f"{BASE_URL}/aliases", json=payload, headers=headers)
    
    if response.status_code == 200:
        return response.json()["alias"]
        
    if response.status_code == 429:
        retry_after = response.headers.get("Retry-After")
        if retry_after:
            wait_time = int(retry_after)
            time.sleep(wait_time)
            retries += 1
            continue
        else:
            # Limit B: Daily Cap hit
            now = datetime.now(timezone.utc)
            raise SystemError(f"Daily cap reached at {now}. Halted until 00:00 UTC.")
            
    if response.status_code == 503:
        retry_after = int(response.headers.get("Retry-After", 5))
        time.sleep(retry_after * (2 ** retries))
        retries += 1
        continue
        
    response.raise_for_status()
    
raise TimeoutError("Exhausted retries due to persistent rate limiting.")

What the Response Actually Contains, So Your Parser Does Not Break

Integrating with programmatic alias generation requires strict adherence to the data contract returned by the Emcognito API. Developers accustomed to standard SaaS boilerplates often assume envelopes such as { "status": "success", "data": { ... } } or root-level identifier fields. Emcognito uses an explicit response structure.

Every successful creation call to POST /v1/aliases returns an HTTP 200 status code. The response body contains an "alias" JSON object with no top-level id or email fields.

The returned alias object contains the following eleven keys:

  • id: A string containing the internal unique identifier for the alias.
  • address: The fully qualified generated email address (e.g., "abc123xyz@emcognito.com").
  • status: A string indicating routing state (e.g., "active").
  • created_at: An integer Unix epoch timestamp in seconds, not an ISO 8601 string.
  • forward_count: An integer representing how many messages have traversed this alias.
  • label: A string identifier provided at creation, or "" if unset.
  • note: A string note for reference, or "" if unset.
  • source: The origin tracking parameter provided at creation, or "" if unset.
  • category: A string categorization tag, or "" if unset.
  • single_use: A boolean flag indicating whether the address auto-deactivates after receiving mail.
  • expires_at: An integer Unix timestamp indicating scheduled expiration, or 0 if unset.

Pay close attention to empty fields. In the Emcognito API contract, unset string fields return as empty strings (""), never as null. If your deserialization layer or typed schemas (such as Zod, Pydantic, or Go structs) expect nullable fields for notes or labels, strict parsers will fail on valid responses. Ensure string validation permits empty string values.

Authentication requires an API key formatted with the literal prefix emk_ followed by 43 URL-safe characters. There is no live or test split: prefixes like emk_live_ or emk_test_ do not exist. Client requests must target https://api.emcognito.com/v1; prepending /api/v1 will return 404 routing errors.

Edge Cases That Produce a 429 You Did Not Expect

Because the gateway and application tiers enforce limits independently, complex infrastructure setups can inadvertently trigger rate limits. The following edge cases account for the majority of unexpected 429 responses:

Concurrent Background Worker Pools

The 60 call-per-minute API burst limit evaluates the token bucket against the specific API key across the entire platform, not per IP address or per running container. If you deploy a Kubernetes pod or worker cluster with four worker processes, each running an independent batch job pulling from a queue, their combined execution rate must remain under 60 calls per minute. If three workers execute a lookup simultaneously while a fourth creates an alias, a sudden queue spike can instantly trigger an HTTP 429.

Microservices Sharing a Common Key

If your user registration service and your automated integration test runner share the same emk_ API key, test suites executing in CI/CD pipelines will consume the production provisioning allocation. Because the burst limiter does not distinguish between test runners and customer registration flows, key sharing will cause intermittent registration failures in staging or production. Ensure distinct automation environments use dedicated billing instances if independent throughput caps are required.

The Midnight UTC Burst Storm

When workers halt execution after hitting the daily alias-creation cap, engineers frequently design queues that sleep until midnight UTC and wake up automatically at 00:00:01 UTC. If a backlogged queue containing hundreds of pending account setups releases all stored jobs simultaneously the instant the clock strikes midnight, that thundering herd immediately trips the 60 calls-per-minute API burst limit. You will transition directly from a daily cap block into a burst limit block. Production architectures should introduce randomized backoff and queue pacing when consuming backlogs after the UTC boundary reset.

What v1 Does Not Do, and How to Work Around It

Architecting reliable integrations requires knowing where an API's boundaries lie. v1 of the Emcognito API creates and lists aliases (GET and POST /v1/aliases). Suspending, resuming and deleting an alias are one-click dashboard actions today; there is no PATCH or DELETE endpoint yet.

Because there is no programmatic method to deactivate an address via the API, a leaked or compromised alias cannot be automatically disabled via code. If your system monitors spam delivery or breach ingestion feeds and flags an address as compromised, your runbook must include logging the affected address and having an administrator log in to suspend it manually from the user interface. Suspending an alias instantly terminates inbound mail processing, dropping subsequent messages permanently.

Identity tracking architecture also requires understanding domain routing. Emcognito aliases use the shared emcognito.com domain. Custom subdomain support is planned, but custom domains are not available today.

Additionally, source availability is fixed. Emcognito is closed source and runs only as a hosted service; if open source or self-hosting is a requirement, addy.io is the better fit. Mail delivery transits Postfix instances and relays via SES over TLS-encrypted connections without application-level encryption; the alias hides your real address from the sender.

Choosing a Plan by API Volume, Not by Inbox Volume

When selecting an Emcognito tier for programmatic use cases, base your decision entirely on daily alias creation requirements rather than monthly forwarding allowances.

Most active accounts forward very little mail each month, making message volume an unhelpful metric when sizing developer infrastructure. What matters for software engineering teams is the creation throughput necessary to support signups, synthetic testing, or dynamic account generation.

Plan Annual Price Developer API Creation Cap Burst Rate Limit Outbound Compose
Emcognito Free $0 No API Access (Dashboard only: 200/day) N/A Unavailable
Emcognito Plus $20 / year ($2 / mo) 50 aliases / day 60 calls / min Included (20 / day cap)
Emcognito Pro $36 / year ($4 / mo) 200 aliases / day 60 calls / min Included (100 / day cap)

As listed on the Emcognito pricing schedule, Plus costs $20 per year (or $2 per month) and provides an API creation cap of 50 aliases per day. Pro costs $36 per year (or $4 per month) for 200 aliases per day via the API. Purchasing Pro annually offers the best value, providing three months free compared to month-to-month billing.

Composing brand-new mail from an alias is the only capability the Free tier cannot do at any usage level. On Free, users can receive forwards and submit replies using Reply securely in the Emcognito delivery log. Composing a brand-new message from an alias is a paid capability on Plus and Pro.

First-time subscribers can evaluate paid features via a 7-day free trial. A credit card is required to initialize the trial, but your account is not billed until the 7-day window concludes.

Frequently Asked Questions

Why does my 429 from POST /v1/aliases sometimes have a Retry-After header and sometimes not?

The Retry-After header only appears when you exceed the 60 calls-per-minute burst limit enforced by the API rate limiter. When your code exceeds the daily alias-creation quota (50 per day on Plus or 200 per day on Pro), the 429 response is generated by application business logic, which omits the header. An absent Retry-After header indicates your account cannot create more aliases until 00:00 UTC.

What time exactly does the daily alias-creation cap reset?

The daily alias-creation cap resets every day at exactly 00:00:00 UTC. The reset occurs on a fixed calendar boundary rather than a sliding 24-hour rolling window. Any quota exhausted in the evening becomes completely accessible again immediately after midnight UTC.

Does GET /v1/aliases count against the daily creation cap?

No, GET /v1/aliases does not count against your daily alias-creation cap. The daily cap applies exclusively to address generation requests routed to POST /v1/aliases. However, all calls to both GET and POST endpoints count toward the standard burst ceiling of 60 requests per minute per key.

Can I suspend or delete an alias through the API when one leaks?

v1 of the Emcognito API creates and lists aliases (GET and POST /v1/aliases). Suspending, resuming and deleting an alias are one-click dashboard actions today; there is no PATCH or DELETE endpoint yet. Disabling an address requires logging into the web dashboard.

The One Next Step

The developer alias API is included with paid plans at 50 aliases a day on Plus ($20/year) and 200 a day on Pro ($36/year). You can view endpoint parameters, response payloads, and code recipes directly on the Emcognito developer documentation.

Sources and further reading

Create aliases from your own code.

Two endpoints, Bearer auth, 50 aliases a day on Plus and 200 on Pro. No PATCH or DELETE yet.

Read the API docs →