DEV Community

Cover image for What Do 402 and 429 Errors Mean, and How Do You Handle API Rate Limits Gracefully?
PDF4me
PDF4me

Posted on

What Do 402 and 429 Errors Mean, and How Do You Handle API Rate Limits Gracefully?

Your integration is humming along, then it isn't. A batch job that ran fine yesterday starts throwing errors halfway through, and the first instinct for most developers is to assume something broke on the server side. Sometimes that's true. More often, with a document API, it isn't a bug at all. It's the API telling you, in HTTP status code form, that you've hit a wall it put there on purpose.

With PDF4me, the two walls you'll run into most often are 402 and 429. They look similar (both are "stop calling me" codes), and it's tempting to treat them the same way in your error-handling code. Don't. They mean different things, they need different fixes, and conflating them is how a five-minute problem turns into a support ticket.

402 is a wallet problem

A 402 response means your account has run out of something you're paying for (or something your free plan gives you for free, up to a point). Per PDF4me's own troubleshooting guide for this exact error, it shows up in two flavors: you've exhausted your credit balance for the current billing period, or you've hit a daily call cap that certain plans enforce. The fix depends on which one it is, and the dashboard is where you find out, not the error message alone.

If it's the daily cap, the counter resets the next calendar day, so a scheduled job that fails at 11pm might succeed if you just retry it at midnight. If it's a genuinely empty credit balance, no amount of retrying fixes it. You need to buy more prepaid calls or move to a plan that fits your actual volume.

The less obvious fix, and the one worth building into your integration from day one rather than after the third 402, is reducing how many calls you're making in the first place. PDF4me's guidance here is straightforward: cache results you already have instead of re-requesting them, batch operations where the endpoint supports it, and eliminate duplicate calls that your own retry logic or a flaky trigger might be generating without you noticing. A workflow that fires the same conversion twice because a webhook retried itself burns exactly the same credits as two genuinely different documents.

Worth knowing while you're in that part of the docs: there's a related 400 error for exceeding a plan's page limit on a single document, separate from the 402 credit story. If a job fails with "page limit exceeded" rather than a credit message, the fix is splitting the file or upgrading, not topping up credits that were never the issue.

429 is a pace problem, and PDF4me doesn't publish the exact number

A 429 is a different animal. It doesn't mean you're out of anything. It means you're calling too fast, and the fix is slowing down, not paying up. Per PDF4me's own API connection reference, which lists the full set of HTTP status codes the V2 REST API can return, 429 is defined plainly as rate limit exceeded, with the recommended fix being exponential backoff and retry.

Here's the part worth flagging honestly rather than guessing past: PDF4me's public documentation doesn't publish a specific numeric threshold for this, no fixed requests-per-second or requests-per-minute figure you can hardcode a check against. That's not a gap in this article, it's a gap in the source material, and inventing a number would be worse than admitting there isn't one. What that means practically is you shouldn't try to precisely calculate your way under a ceiling you can't see. Build defensively instead: treat 429 as a signal to pause and retry, not a bug to chase down.

A minimal, honest pattern looks like this in Python:

import time
import random
import requests

def call_pdf4me(url, headers, payload, max_retries=5):
    for attempt in range(max_retries):
        response = requests.post(url, headers=headers, json=payload)
        if response.status_code == 429:
            wait = (2 ** attempt) + random.uniform(0, 1)
            time.sleep(wait)
            continue
        return response
    raise Exception("Gave up after repeated 429 responses")
Enter fullscreen mode Exit fullscreen mode

Exponential backoff with a bit of random jitter (rather than every failed request retrying at the exact same intervals) is the standard shape for this, and it's what the docs point toward even without a published threshold to tune it against. If your traffic pattern is more "burst of 200 documents at once" than "steady trickle," the better fix often isn't a smarter retry loop at all, it's using PDF4me's asynchronous processing instead of hammering the synchronous endpoint. For large files or batch operations, the API can return a jobId instead of an immediate result, which you then poll via GET /api/v2/JobResult/{jobId} until it reports success. That single change, batching through async rather than firing dozens of synchronous requests in a tight loop, quietly removes most of the conditions that produce a 429 in the first place.

Log the status code, not just "it failed"

A cheap habit that pays off the first time you actually need it: log the raw HTTP status code alongside every failed PDF4me call, not just a generic "request failed" message. Six months into production, "we saw 40 errors last week" tells you nothing. "38 were 429s clustered around our 9am batch job, 2 were genuine 402s from a plan we'd outgrown" tells you exactly what to fix and in which order. This is especially worth doing before you reach for a support ticket. PDF4me's status codes are specific enough (400, 401, 402, 403, 404, 429, 500, each with a distinct meaning) that a log line with just the number, timestamp, and endpoint usually answers "is this us or them" before anyone has to ask.

They're easy to confuse with 401, so don't

There's a third code worth mentioning in the same breath, if only to rule it out. A 401 Unauthorized error also stops your request cold, but for an unrelated reason: a missing, malformed, or revoked API key, most commonly because the Base64-encoded Authorization header is missing its trailing colon. If your error-handling code branches on "did the request fail," it's worth branching further on the actual status code before deciding whether the fix is "wait and retry" (429), "check the dashboard" (402), or "check the key" (401). Treating all three as the same failure mode means you'll spend time debugging a rate-limit issue as if it were a credentials issue, or vice versa.

PDF4me's broader troubleshooting index is worth bookmarking for exactly this reason: it's organized by symptom, not buried in a single giant FAQ, which makes it faster to confirm which of these you're actually looking at before you start writing retry logic for the wrong problem.

If you're not calling the REST API directly

Not every PDF4me integration hits api.pdf4me.com from application code. If you're going through Power Automate, Zapier, Make, or n8n instead, the connector sits between you and the raw HTTP layer, but the underlying account limits (credits, daily caps, pace) still apply exactly the same way, since they're account-level, not code-level. What changes is how you see the failure: instead of catching a 429 in a try/except block, you're more likely to see a failed flow run or a stalled Zap, which is a worse debugging experience precisely because the status code is hidden a layer down. PDF4me's Zapier and Power Automate troubleshooting tips cover several of the no-code-specific gotchas that show up here, like binary data not being recognized correctly between steps, which can look like a rate-limit failure but isn't one.

Test without spending the calls that matter

One more habit worth building in: you don't need to burn production credits, or risk tripping a 429 on a live pipeline, just to check whether a request shape is correct. PDF4me's interactive API Tester lets you paste your key, upload a file, and run a real request straight from the browser, which is a much cheaper place to debug a malformed payload than inside a scheduled job that's already mid-retry. And if you're troubleshooting credit consumption specifically, the fastest first step is checking actual usage against your plan in the PDF4me dashboard rather than guessing from the error message alone. If you haven't generated a key yet, the Getting Started guide walks through creating an account and making your first authenticated request, which is also where you'll find where the dashboard lives day to day.

Build for both, once, and stop thinking about them

None of this is complicated once it's in place. A 402 needs a dashboard check and either a wait, a top-up, or a plan change. A 429 needs backoff, jitter, and ideally fewer synchronous calls in the first place, via async processing or basic caching. Neither is a sign your integration is broken; they're both the API doing exactly what it's supposed to do when it hits an account-level or pace-level ceiling. Build the handling once, put it in whatever wrapper function or middleware sits between your code and PDF4me's API, and you'll stop noticing these errors at all, which is the actual goal.

Website: pdf4me.com
Documentation: docs.pdf4me.com
Developer portal: dev.pdf4me.com

Top comments (0)