Understanding the limitations of v1
Version 1 covers the main moments of a referral: a referrer joins, a friend’s order is pending, a referral succeeds. Some changes send no event, and a few fields follow rules that are easy to miss. Read this page before you build an integration that must never miss a change.
When an event is missing, the API is the fallback: run a regular sync with updated_since to catch up.
Changes that send no webhook
Section titled “Changes that send no webhook”- A referral is rejected. A pending referral that is rejected, for example after a fraud check or a manual review, sends no event.
referral.pendingis the last event for it. - Referrals approved right away.
referral.pendingis sent only when Bloop holds a referral for approval. A referral approved right away sends onlyreferral.succeeded. - A reward is revoked after a refund. When a refund revokes a reward after
referral.succeeded, no event follows. - A referrer leaves a campaign. No event. The membership
statusbecomesinactiveand the referrer’supdated_atchanges, so a sync finds it. If they join again later, Bloop sends a newreferrer.joinedwith a newjoined_at. - Referrers added by a bulk import. Imported referrers send no
referrer.joinedwhen they are imported. They appear in the API withsource: imported. - Referral orders you add by hand. A referral order you add with Add order on the Orders tab does not send
referral.pending. It sendsreferral.succeededwhen it is approved, which is right away unless its reward needs your approval. - Referrals approved by an older approval schedule. A small number of referrals scheduled for approval before version 1 went live are approved without
referral.succeeded. - While your plan does not include the API, or Bloop is uninstalled. Events are skipped and never delivered later, even after you upgrade or reinstall.
- While an endpoint is disabled. Events are not kept for it. Deliveries that were still waiting when it was disabled are marked failed and not sent later.
- In the first 60 seconds after you add an endpoint or subscribe it to an event. Events in that window can be missed.
- During a Bloop incident. If Bloop cannot confirm your subscriptions, or cannot hand the event over for delivery, at the moment the event happens, that event is not sent.
- An approval that fails partway. If an approval fails partway through, the referral can end up approved without
referral.succeeded.
Events that arrive late
Section titled “Events that arrive late”referrer.joinedwaits for the discount code. In a campaign that gives referrers a personal discount code, the event is sent only once the code exists. If Shopify refuses to create the code, the event arrives later, when the code is created. If the code is never created, no event is sent.- Delivery stops after 7 attempts. After the last retry, about 21 hours after the event, the delivery is marked failed. Bloop does not send it again by itself. You can resend it from the app for 30 days.
- Customers who ask to erase their data. When a customer asks Shopify to erase their data, Bloop removes their details from stored events and cancels deliveries still waiting. Those events can no longer be resent.
Changes that do not move updated_at
Section titled “Changes that do not move updated_at”updated_at changes when the referrer or one of their memberships changes in Bloop. It does not change when:
- the customer’s name changes in Shopify (
first_name,last_name); - you rename a campaign (
campaign_name); - you change your sharing domain (
share_link); - a referral is rejected after its reward was issued:
referral_revenuedrops butupdated_atstays.
The API returns the values Bloop holds at the time of the request. Names come from the copy Bloop keeps from Shopify, so they can lag behind Shopify. For the latest name, look the customer up in Shopify by shopify_customer_id. When you need an exact referral_revenue, read the referrer again instead of relying on updated_at.
Field rules to know
Section titled “Field rules to know”source. Referrers created by any import reportimported. A source Bloop cannot map reportsunknown.join_source.storefrontis a join on your storefront, and also the value when Bloop cannot tell where the join came from, for example a referrer you invite from the admin or import.segmentis a real-time update from a Shopify segment.segment_syncis a bulk re-sync after the audience of a campaign changed.successful_referralsandreferral_revenuecan disagree.successful_referralscounts pending referrals as well as approved ones.referral_revenueadds up approved referrals only.- Currencies.
referral_revenueand reward amounts use your store currency.order.totaluses the currency of the order. If your store changed currency,referral_revenuecan mix amounts in both currencies. order.nameis#followed by the order number, for example#1043. A custom prefix or suffix you set for order names in Shopify is not included.referral.orderandreferral.referee.emailcan benull.orderisnullwhen Bloop has no order record for the referral, which can happen for referrals created before version 1.referee.emailisnullwhen the referee has no email, for example a referral you add by hand without one. The event is still sent, so check fornullbefore you readorder.totalor match on the email.joined_atis the most recent time the referrer joined the campaign, not the first.referee.discount_codeisnullfor referrals you add by hand.reward.valueandreward.value_typearenullfor discount code rewards issued before version 1.rewardcan benullinreferral.succeeded. The approval issued no reward: the campaign needs more referrals first, the next tier is not reached, rewards are turned off, or you add a referral by hand without sending a reward. It is alsonullwhen you add a referral by hand and the reward could not be created at that moment, even if you create it later.- Timestamps carry milliseconds. The envelope
created_atand theX-Bloop-Triggered-Atheader look like2026-10-01T03:12:00.123Z. Parse them as RFC 3339 times instead of matching one exact format.updated_atin the API has second precision. - The signing key is the whole secret. Compute the webhook signature with the full secret, including the
whsec_prefix. A secret without the prefix gives a different signature. planinGET /v1/meis a display name. Don’t branch on it.
Request rules to know
Section titled “Request rules to know”- Encode
+in emails. A+sent as is in a query string is read as a space. Send[email protected]assomchai%2Bline%40example.com. - Every request that passes the key and store checks counts toward the rate limit, including
GET /v1/meand requests that fail with400,403 insufficient_scopeor404. Bloop checks a request in this order: key, store access, rate limit, path, scope, parameters. - Only
GETexists. Any other method, includingOPTIONSandHEAD, returns404 not_foundonce the key is valid. GET /v1/meandGET /v1/referrers/{id}take no query parameters. Adding one returns400 invalid_request.- Email lookups are not checked for email format. Any non-empty value up to 320 characters is accepted, and a value that matches no referrer returns
404 referrer_not_found. - A malformed referrer id is a
404, not a400.GET /v1/referrers/abcreturns404 referrer_not_found, the same answer as an id that does not exist. 503 service_unavailableis temporary. Wait the number of seconds inRetry-Afterand retry.- No browser calls. The API sends no CORS headers.
- A list can return a referrer twice when it changes while you page. It is never skipped.
- Read-only. Version 1 has no endpoint that creates or changes data, and no endpoint that lists referrals or campaigns.
- Keys don’t expire, and their scope is fixed. The scope is set when a key is created and cannot be changed later.
Common mistakes to avoid
Section titled “Common mistakes to avoid”- Treating
referral.succeededas final. A refund can revoke the reward later without an event. - Reporting
successful_referralsas approved referrals. It includes pending ones. - Relying on webhooks alone. Pair them with a scheduled sync.
- Removing
whsec_from the secret. Verification then fails for every webhook.
Next steps
Section titled “Next steps”- Build the fallback sync in How to make your first API call.
- Set up retries and dedupe in How to receive webhooks.
- Check field definitions in Understanding webhook events.

