Share a Wish

Rate Limits & Usage

Share a Wish meters two different things. Wishlist actions are the billing unit of every plan. Per-key rate limits are a technical safeguard reported in response headers. Rate limits never reject requests (there is no 429). Above the monthly action quota, paid plans keep working and pay per additional action (overage); the Free plan is paused at 100% and POST /widget/save answers 402 usage_limit_reached until the next calendar month or an upgrade.

Wishlist actions — the billing unit

One value unit for all shop plans. An action is one of:

ActionCounted whenDeduplication
saveA product is saved successfully via the widget or a hosted page (/widget/save, /hosted/save).One per successful save.
shareA list that contains your products is made public.One per list and calendar day.
list_viewA public hosted list containing your products is viewed.One per list, viewer and 10-minute window.

Actions are attributed to the partner that supplied the most recently added item of a list. The metering period is the current calendar month (UTC). API calls themselves — including POST /widget/init — are not a pricing dimension.

Per-plan limits

PlanPrice / monthIncluded wishlist actions / monthOverage per extra actionWebhooksServer keys
Free0 €200— (hard stop: saves are rejected with 402)nono
Starter19 €2,0002.5 ctnono
Growth49 €15,0001.0 ctyesno
Scale99 €60,0000.5 ctyesyes
Enterpriseindividualindividual (treated as unlimited)individualyesyes

Test keys (pk_test_…) can be created on every plan. The plan is the same whether you subscribe through the Partner Portal or through Shopify billing (see Shopify plans).

Overage & Free-plan hard stop

Paid plans (Starter, Growth, Scale): nothing is switched off at 100%. Every wishlist action above the included quota is billed at the plan's per-action overage rate (Starter 2.5 ct, Growth 1.0 ct, Scale 0.5 ct) at the end of the calendar month. An upgrade is always cheaper than sustained overage: Growth beats Starter from 1,200 actions over the limit, Scale beats Growth from 5,000. Enterprise has an individual quota and rate.

Free plan: 200 actions per calendar month, no overage. At 100% the wishlist is paused: POST /widget/save (and the hosted save page) reject further saves with HTTP 402 until the next calendar month starts or the partner upgrades. Shares and list views are still counted but not blocked.

HTTP/1.1 402 Payment Required
{
  "error": "usage_limit_reached",
  "message": "Monthly wishlist-action limit of the Free plan reached.",
  "plan": "free",
  "actions_limit": 200,
  "upgrade_url": "https://partner.shareawish.shop/subscription"
}

Handle 402 like a soft failure: show the end customer a friendly "wishlist is paused" notice, do not retry automatically. The hosted save dialog (shareawish.shop/save), which the Save Button SDK opens, already does this — SDK integrations need no extra code; only direct POST /widget/save callers have to handle the status themselves.

80% / 100% notifications

After each recorded action the API compares the month's total with the plan limit. At 80% (USAGE_WARNING_THRESHOLD) and at 100% (USAGE_LIMIT_THRESHOLD) the partner receives one e-mail per threshold and period, and the Partner Portal shows a warning or upgrade banner. Notifications are deduplicated per partner, period and threshold. On paid plans the excess is visible as overage in the /widget/init response and as overage actions and cost in the portal; on Free the portal shows the paused state. Plans without a finite limit (Enterprise) never trigger notifications.

Response headers

Wishlist-action usage on POST /widget/init

HeaderMeaning
X-Usage-TotalWishlist actions recorded for the partner this calendar month.
X-Usage-LimitIncluded actions of the plan.
X-Usage-Remainingmax(0, limit − total).

The JSON body of the same response carries overage: true once the total exceeds the limit. These headers are informational; enforcement happens only on POST /widget/save for the Free plan (402, see above).

Per-key rate-limit headers on /widget/*, /hosted/*, /shops/*, /baskets/*, /products/*

A middleware resolves your API key from the Authorization: Bearer pk_… header or the widget token, calls the rate-limit function, increments a per-key counter and sets these headers. The values are informational: a request over the per-minute limit is not rejected and there is no 429. Billing happens on wishlist actions, not on requests. If the key cannot be resolved (e.g. an unauthenticated public list read) the headers are absent.

HeaderMeaning
X-RateLimit-LimitRequests per minute allowed for the key's plan.
X-RateLimit-RemainingRemaining requests in the current minute (never below 0; informational).
X-RateLimit-ResetISO timestamp when the minute window resets.
X-Usage-MonthRequests counted for this key in the current calendar month.
X-Usage-LimitIncluded monthly requests of the key's plan.
X-Usage-OverageOverage amount accrued this month.

Note the name clash: X-Usage-Limit on /widget/init is the plan's wishlist-action limit; on the other routes it is the per-key request allowance of the legacy API-call model. The rate-limit function skips OPTIONS preflights and the /health and /analytics/* paths.

Checking your usage

  • Partner Portal → Subscription shows used / included actions, a breakdown by save / share / list view, the warning level and the period.
  • GET /me/usage (portal user token) returns { plan, plan_name, actions_used, actions_limit, period_start, period_end, breakdown, percent, level, trial_days } where level is ok, warning (≥ 80%) or exceeded (≥ 100%) — plus the overage fields hard_limit, overage_per_action_minor (cents, null on Free / Enterprise), overage_actions, overage_cost_minor, next_plan, upgrade_cheaper_from_actions and blocked (Free plan paused).
  • GET /api-usage/{apiKeyId} (authenticate with the key itself) returns the per-key request counters and the key's plan limits used for the X-RateLimit-* headers.

FAQ

Will my integration break when I hit the limit?

Not on a paid plan: the API never returns 429, the widget keeps working at 100% and every additional wishlist action is billed as overage (Starter 2.5 ct, Growth 1.0 ct, Scale 0.5 ct per action). On the Free plan saving pauses at 100%: POST /widget/save answers 402 usage_limit_reached until the next calendar month or an upgrade. You get an e-mail at 80% and 100% of the quota and an upgrade banner in the Partner Portal.

What does 402 usage_limit_reached mean?

A Free-plan partner has used its 200 wishlist actions for the calendar month. POST /widget/save rejects further saves with HTTP 402 and the body { error: 'usage_limit_reached', message, plan: 'free', actions_limit, upgrade_url }. Show the end customer a friendly "wishlist paused" notice, do not retry automatically. Paid plans never receive this error; they pay per extra action instead.

Does POST /widget/init count against my quota?

No. Only saves, shares and hosted list views are wishlist actions. Init calls are logged for analytics and the per-key request counters but are not billed.

Do test keys count?

Test keys are available on every plan and their requests are counted by the per-key rate-limit counters. Saves made with a test key are flagged as test traffic in analytics.