ShopEazydevelopers
Concepts

Rate limits

The daily caps, the 429 answer and its headers, and what is never limited.

The limits are generous on purpose. A normal shop never meets them. A looping script or a runaway AI app does within minutes.

Storefront API

No Storefront API operation has an application limit today. If one is added, it will say so on the operation, and it will answer as described below.

Merchant API

There are two kinds of limit. Both are counted per UTC day, and reset at 00:00 UTC, which is 02:00 in South Africa.

Per store, per day, for everyone

These count against the store, not the person or the app.

AllowancePer dayOperations
aiGenerations300draftProduct, generateProductCopy, generateImage, designForMe, buildPageWithAi, startStudioMake
emailSends100sendCampaign, sendTestEmail, remindBaskets, remindToPay. One per call, whatever the number of recipients
whatsappSends500sendWhatsAppMessage

A call that is then refused or fails gives its place back. Bulk product imports have a daily cap too (20 runs a store), but it is applied in the console, not on this API.

Per connected AI app, per day

These apply only to a connection made through Merchant OAuth. The ShopEazy app's own sign-in has none.

AllowancePer day
addPhotos200 photos
bookCollection50 courier bookings

Credits are separate. A connection also has a monthly credit limit that the merchant sets, which answers 403 over_credit_limit, not 429.

The 429 answer

Every limit answers 429 rate_limited:

HTTP/1.1 429 Too Many Requests
Retry-After: 21600
RateLimit-Limit: 300
RateLimit-Remaining: 0
RateLimit-Reset: 21600
X-Request-Id: 7c9e6679-7425-40de-944b-e07fc1f90ae7
{
  "error": {
    "code": "rate_limited",
    "message": "This store has used its 300 AI generations for today. They come back at midnight UTC (02:00 in South Africa).",
    "requestId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "details": { "limit": 300, "remaining": 0, "retryAfter": 21600 }
  }
}
HeaderMeaning
Retry-AfterSeconds to wait before you try again
RateLimit-LimitThe cap for the window. Left out when a limit cannot name its cap
RateLimit-RemainingCalls left in the window. 0 when you are refused
RateLimit-ResetSeconds until the window resets. The same number as Retry-After

error.details carries limit, remaining and retryAfter. For a daily cap, retryAfter is the wait until the next 00:00 UTC.

A refused call did nothing and used nothing. Send the same call again after the wait, with the same Idempotency-Key if it has one.

On the Storefront API a browser may read these headers, as the API exposes them.

What is never limited

Payment-provider callbacks, webhooks and /health are never rate limited. A provider that gets a 429 retries or gives up, which would lose or delay a payment.

On this page