How to make your first API call
This guide takes you from no key to a working lookup in a few minutes. You need a store on the Premium plan (Scale on older plans), and a server or a terminal where the key stays private.
Create an API key
Section titled “Create an API key”- In Bloop, open Settings, select the Integration tab, then select Manage on the API & Webhooks card.
- Under API keys, select Create API key. In Key name, type a name that tells you where the key is used, for example
LINE bot, then select Create API key. - Copy the key from the Secret key field. It starts with
bloop_sk_and is shown only once: Bloop keeps a fingerprint of the key, not the key itself, so nobody can show it to you again. - Select I’ve saved the key to close the window. Until you do, the window cannot be closed.
The list of keys shows each key’s Name, its first characters (Key), its Permissions, when it was Last used and who created it. A store can have up to 5 active keys. In version 1 every key has the referrers:read scope, shown under Permissions.
Keep the key safe
Section titled “Keep the key safe”- Call the API from your server only. The API sends no CORS headers, so a browser blocks calls from a theme, a storefront script or any web page.
- Never put the key in theme code, a mobile app or a code repository.
- Lost a key? Create a new one, switch your integration to it, then revoke the old one. A revoked key stops working within 60 seconds.
- Keys do not expire. Revoke the keys you no longer use.
Check the key
Section titled “Check the key”GET /v1/me works with any key and returns your store, plan, scopes and limits. Use it to confirm that the key works.
curl https://api.bloop.plus/v1/me \ -H "Authorization: Bearer bloop_sk_YOUR_KEY"{ "data": { "shop": "your-store.myshopify.com", "plan": "Premium", "scopes": ["referrers:read"], "limits": { "requests_per_minute": 100, "api_keys": 5, "webhook_endpoints": 5 }, "key": { "name": "LINE bot", "prefix": "bloop_sk_uZT" } }}401 invalid_api_key means the key is missing, mistyped or revoked. A 403 means the store cannot use the API right now. Every code is explained in Understanding errors and rate limits. plan is a display name, so don’t branch on it.
Look up a referrer
Section titled “Look up a referrer”Look up by Shopify customer id when you have it. The id never changes, while a customer can change their email.
curl "https://api.bloop.plus/v1/referrers?shopify_customer_id=7012345678901" \ -H "Authorization: Bearer bloop_sk_YOUR_KEY"Both 7012345678901 and gid://shopify/Customer/7012345678901 work. The response always gives the numeric form.
To look up by email, let curl encode the value:
curl -G https://api.bloop.plus/v1/referrers \ -H "Authorization: Bearer bloop_sk_YOUR_KEY"Email matching ignores case and spaces around the value. It also finds a referrer through the customer’s current Shopify email when that differs from the email Bloop stored. A lookup returns one referrer:
{ "data": { "id": "12345", "shopify_customer_id": "7012345678901", "first_name": "Somchai", "last_name": null, "source": "auto_enrolled", "created_at": "2026-10-01T03:12:00Z", "updated_at": "2026-10-01T03:12:00Z", "campaigns": [ { "campaign_id": "88", "campaign_name": "VIP referral", "status": "active", "joined_at": "2026-10-01T03:12:00Z", "share_code": "AB12CD34", "share_link": "https://refer.example.com/AB12CD34", "discount_code": "REF_AB12CD34", "successful_referrals": 3, "referral_revenue": { "amount": "120.00", "currency": "THB" } } ] }}No match returns 404 referrer_not_found, and so does a referrer of another store or an id that is not a valid referrer id. To read a referrer by the Bloop id you received in a webhook:
curl https://api.bloop.plus/v1/referrers/12345 \ -H "Authorization: Bearer bloop_sk_YOUR_KEY"What a referrer contains
Section titled “What a referrer contains”Each entry in campaigns is one campaign the referrer belongs to:
| Field | What it holds |
|---|---|
share_link |
The referrer’s personal referral link for this campaign |
share_code |
The code at the end of the link |
discount_code |
The referrer’s personal discount code. null when the campaign does not use share codes, or while the code is not created yet |
status |
active or inactive (the referrer left the campaign) |
joined_at |
When the referrer most recently joined the campaign. Joining again after leaving sets a new time |
successful_referrals |
Referrals counted for the referrer in this campaign |
referral_revenue |
Revenue from the referrer’s approved referrals |
Every id is an opaque string: store it as text, never parse it or compare ids by size. All fields are described in Understanding the API endpoints.
Sync every referrer
Section titled “Sync every referrer”To build or refresh your own copy of your referrers, list the ones that changed since a point in time and follow the cursor.
- Call
GET /v1/referrers?updated_since=2026-10-01T00:00:00Z&limit=100. - Save each referrer by
id. - While
next_cursoris notnull, call again with the same filters pluscursor=<next_cursor>. The cursor only marks a position: it does not remember your filters. - When
next_cursorisnull, keep the largestupdated_atyou saw. Start the next sync from it.
const BASE = 'https://api.bloop.plus/v1/referrers';
async function syncReferrers(key, since, save) { let cursor = null; let newest = since; for (;;) { const params = new URLSearchParams({ updated_since: since, limit: '100' }); if (cursor) params.set('cursor', cursor); const res = await fetch(`${BASE}?${params}`, { headers: { Authorization: `Bearer ${key}` } }); if (res.status === 429 || res.status === 503) { const wait = Number(res.headers.get('Retry-After') || 5); await new Promise((resolve) => setTimeout(resolve, wait * 1000)); continue; } if (!res.ok) throw new Error(`Bloop API ${res.status}: ${await res.text()}`); const page = await res.json(); for (const referrer of page.data) { await save(referrer); if (Date.parse(referrer.updated_at) > Date.parse(newest)) newest = referrer.updated_at; } if (!page.next_cursor) return newest; cursor = page.next_cursor; }}updated_sinceneeds a time zone,Zor an offset like+07:00. Without one you get400 invalid_request.limitgoes from 1 to 100 and defaults to 50. A value outside that range returns400, it is not adjusted for you.- Add
campaign_idto list only the members of one campaign. Acampaign_idthat does not exist in your store returns404 not_found. - A referrer that changes while you page moves to the end of the list and can appear twice. It is never skipped. Keep the copy with the newer
updated_at. - Lookup parameters (
email,shopify_customer_id) cannot be mixed with list parameters, andemailcannot be combined withshopify_customer_id. An unknown or repeated parameter returns400, so a typo fails loudly instead of returning a list.
Common mistakes to avoid
Section titled “Common mistakes to avoid”- Building the URL by hand with a raw email. A
+turns into a space and the lookup misses. - Looking up by email when you have the customer id. Customers change emails; ids stay.
- Restarting a sync from the beginning every time. Save the largest
updated_atand continue from it. - Reusing a cursor with different filters. Send the same filters with every page.
- Calling the API from a browser. It fails, and it would expose your key.
Next steps
Section titled “Next steps”- See every endpoint and field in Understanding the API endpoints.
- Handle errors and limits in Understanding errors and rate limits.
- Get changes pushed to you in How to receive webhooks.

