Troubleshooting Developers

HTTP 429 and rate limit errors

Tell which limit caused a 429: plan limit (rate_limited), IP limit (Too Many Attempts), the public tracking link page, sign-in or OTP routes, and what to do about each.

Last updated 22 October 2026 · Last verified 22 October 2026

What it means#

HTTP 429 ("too many requests") means a limit was reached and the request was not carried out: nothing is created or charged. The platform has several independent limits, and the shape of the answer shows which one you hit.

Who is affected#

Developers calling /api/v1 (merchant key) or /api/company/v1 (company key), visitors of public pages such as the parcel tracking link page, people signing in or registering, and users of the mobile apps.

Likely causes#

What you receive Limit reached Counted per
JSON with error.code rate_limited, error.retry_after and a Retry-After header Your plan's per-minute or per-day API limit Account
JSON {"message": "Too Many Attempts."} with Retry-After, X-RateLimit-Limit and X-RateLimit-Remaining IP limits: 60 requests per minute across all of /api, then route limits such as a configured 60 for POST /api/v1/parcels and 30 for GET /api/v1/statement, which are reached after about half as many requests (see below) IP address
An HTML page: "Too Many Requests received. Please try again later." with an "Error reason" box and a reference starting with H The same IP limits when the request has no Accept: application/json, and page limits such as the public tracking link page /t/{tracking} (60 per minute) IP address, or the user when signed in
Sign-in form: "Too many login attempts. Please try again in N seconds." (the Arabic text shows no number) 5 failed attempts with the same email or mobile from one IP address; locked for about a minute. Counted for unknown logins and for a company's own accounts on its own site. A wrong password for an existing account on the other kind of site (for example a company or merchant account on the central domain) is rejected without being counted Login name and IP
Mobile app calls (same answers as above) resend-otp 3 per minute; otp-verification, signin, deliveryman/login and login 10 per minute; register and password/email 5 per minute IP address
Merchant sign-up at /join: "Too many accounts were registered from this device today — try tomorrow or contact support." 5 accounts per device per day, and 5 submissions per minute IP address
Guest shipping at /ship (order form): "Too many requests from your device — try again after N minutes." Order submissions: 20 per day per device IP address
Guest shipping at /ship (price box): "Too many requests — wait a minute and try again." The real wait can be up to an hour. A direct call to the price check answers JSON with the text "Too many requests from your device — try again after N minutes." Price checks: 300 per hour per device. The page shows this short text for any 429 on the price check, per-minute limits included IP address

Good to know:

  • IP counters are shared. All routes with a plain per-minute limit add to one counter per IP address, whichever domain or host the request used, so all keys and applications behind the same public IP address share it. Routes that have their own limit inside an already limited group count twice: POST /parcels, GET /statement, POST /webhooks, the webhook test (POST /webhooks/{id}/test) and the company POST /parcels. The usable rate on those routes is therefore roughly half of the configured route limit (for example about 30 parcel creations per minute with the merchant API), and never more than the 60 per minute that apply to all of /api.
  • Fixed windows. A minute window starts at the first counted request. The daily plan counter resets at 00:00 UTC.
  • Plan values. A new plan form is pre-filled with 60 per minute and 5,000 per day (merchants) or 120 and 20,000 (companies). Empty or 0 means no limit.
  • Message text. Plan-limit messages are localized, and the English text can read awkwardly, for example "You have reached your plan limit: 60 order Per minute. Wait 42 seconds or upgrade your plan."

How to diagnose#

Repeat a call with -i and Accept: application/json, then read the body and headers:

bash
curl -i https://YOUR_DOMAIN/api/v1/me \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
  • rate_limited is your plan. Merchants open Plan and subscription and read API requests today under Your plan usage. Company admins read the usage on Integrations and API, or call GET /api/company/v1/me.
  • Too Many Attempts. is an IP limit. Compare X-RateLimit-Limit with the number of calls per minute made from your whole public IP address, including other applications.
  • An HTML page means the request had no JSON Accept header, or it was a page. Note the H… reference and the time.

Resolution steps#

  1. Wait for the window

    Pause for the Retry-After seconds (or retry_after) and then retry. A daily plan limit can mean a wait of hours.

  2. Slow down and spread the calls

    Add a delay with a random jitter between calls and avoid many workers from one IP address. Cache lists that rarely change, such as /governorates and /companies, and use webhooks instead of polling.

  3. Retry creation safely

    Send a reference with POST /parcels so a repeated request is recognised. On the merchant API a retry returns the existing parcel (HTTP 200, "duplicate": true) instead of creating another one. On the company API the same reference for the same merchant returns 409 duplicate_reference: treat it as already created and fetch the parcel with GET /parcels/{reference} (that lookup covers all merchants of your company, so if they can share a reference, use GET /parcels?reference=…&merchant_id=…). The idempotency article has the details.

  4. Raise the plan limit

    If you hit the plan limit regularly, ask the platform to move you to a plan with higher limits. Plan limits are set per plan by the super admin; the IP limits are fixed and cannot be raised per account.

A tracking link the merchant shares with the customer (demo data)

When to contact support#

  • You get 429 at low volume although only your own system uses the IP address.
  • The usage counter in the panel does not match your calls.
  • Quote the H… reference, the URL and the time when you report an HTML 429 page.

API

  • GET /api/v1/me
  • POST /api/v1/parcels
  • POST /api/company/v1/parcels
  • GET /api/company/v1/me