API reference
Fisher watches for brand-new Shopify, WooCommerce, WordPress, Squarespace and Wix sites the moment they appear and hands them to you, confirmed live and enriched. The API gives your own software the same feed the dashboard shows: pull it on demand, or have new matching stores pushed to you in real time with webhooks.
The API is available on the Enterprise plan. Everything is a plain HTTPS request that returns JSON, so it works from any language or tool. The base URL for every endpoint is:
https://fisherleads.com/v1Quick start
Three steps to your first result:
- Open Dashboard, then Developers, and generate an API key. Copy it — it is shown only once.
- Send it as a bearer token on every request.
- Call
/v1/leadsand start filtering.
curl "https://fisherleads.com/v1/leads?platform=shopify&country=US" \
-H "Authorization: Bearer fk_live_your_key_here"That returns the newest US Shopify stores as JSON, newest first. Add filters to narrow it, or a webhook to get them pushed to you automatically instead of polling.
Authentication
Every request is authenticated with your secret API key in the Authorization header, as a bearer token. Keys begin with fk_live_.
Your key is shown once, at creation, and only its hash is stored on our side, so we can never show it to you again. Treat it like a password: keep it on your server, never commit it to a repo, and never ship it in a browser or mobile app where a user could read it. If a key leaks, revoke it in the dashboard and generate a new one — revoking takes effect immediately. You can hold several keys at once (for example one per environment) and rotate them independently.
Authorization: Bearer fk_live_your_key_hereRate limits and usage
Each key may make up to 120 requests per minute, plus a generous monthly call allowance. Go over either and the API responds with 429 Too Many Requests; wait and retry. If you are paginating a large pull, a short pause between pages keeps you comfortably under the limit.
Check where you stand at any time with GET /v1/me:
/v1/meYour plan, per-minute limit, monthly cap, and calls used so far this month.
{ "plan": "enterprise", "rate_limit_per_min": 120, "monthly_cap": 100000, "used_this_month": 812 }List leads
/v1/leadsThe live feed as JSON, newest first, paginated. Accepts the same filters as the dashboard.
Filters
All parameters are optional and combine with AND. Leave them off to get the whole feed.
platformshopify, woocommerce, wordpress, squarespace, wix. Comma-separate for several.countryISO country code, e.g. US, GB, DE. Comma-separate for several.site_typeecommerce or service.nicheCategory, e.g. beauty, apparel, home.techOnly stores running a given app or tech, e.g. Klaviyo.has_emailtrue to return only stores with a public contact email.seen_after / seen_beforeFilter by the day a store was added to Fisher (YYYY-MM-DD). seen_before is exclusive, so one day = [day, next day).launched_after / launched_beforeFilter by the store's own launch date (first SSL certificate).page / page_sizePagination. page starts at 1; page_size up to 200 (default 100).The response wraps the page in total (matches across the whole filter), page, page_size and items. To page through everything, request page=1, then 2, and so on until you have collected total rows.
curl "https://fisherleads.com/v1/leads?platform=shopify&country=US&has_email=true&page_size=50" \
-H "Authorization: Bearer fk_live_your_key_here"
{
"total": 4231,
"page": 1,
"page_size": 50,
"items": [
{
"domain": "example.com",
"url": "https://example.com",
"platform": "shopify",
"site_type": "ecommerce",
"country": "US",
"niche": "beauty",
"launched": "2026-06-30",
"registered": "2026-06-24",
"merchant": "Example Beauty Co",
"product_count": 42,
"email": "[email protected]",
"socials": { "instagram": "https://instagram.com/examplebeauty" },
"tech": ["Klaviyo", "Meta Pixel"]
}
]
}Get one lead
/v1/leads/{domain}A single enriched store by its apex domain. Returns 404 if it is not a live store in the feed.
curl https://fisherleads.com/v1/leads/example.com \
-H "Authorization: Bearer fk_live_your_key_here"Response fields
Every lead carries the same fields the dashboard shows. A field is omitted or null when we could not confirm it.
domain / urlThe store's apex domain and its https URL.platformThe ecommerce or site platform it runs on.site_typeecommerce (sells products) or service (a business or brochure site).countryBest-confirmed country, as an ISO code.nicheBest-guess category from its products or content.launchedWhen the site went live, from its first SSL certificate.registeredWhen the domain was registered (RDAP), when known.merchantStore or brand name.product_countNumber of products (precise on Shopify).emailPublic contact email, when the store publishes one.socialsObject of social profiles found, keyed by network.techApps, pixels and tools detected on the store.Errors
The API uses standard HTTP status codes. The body is always JSON with a detail message you can log.
200Success.401Missing, invalid or revoked API key.403The key is valid but the account is not on Enterprise.404No live store with that domain.429Rate limit or monthly cap reached. Wait and retry.Webhooks
Instead of polling the feed, let Fisher push new matching stores to you the instant they go live. Add a webhook in the dashboard under Developers: a URL to receive events, and an optional filter (for example Shopify, US, has email) so you only get the stores you care about.
When new stores match, we send a single signed POST to your URL with the batch of leads. Each lead has the same shape as the API above.
POST https://your-server.com/hook
Content-Type: application/json
X-Fisher-Event: leads.new
X-Fisher-Signature: 3a7f... (hex hmac-sha256 of the raw body)
{ "event": "leads.new", "count": 3, "leads": [ { "domain": "...", "platform": "...", ... } ] }Verifying a delivery
So you know a request really came from Fisher, every delivery is signed. Compute an HMAC-SHA256 of the raw request body using your webhook secret (shown next to the webhook in the dashboard) and compare it, constant-time, to the X-Fisher-Signature header.
// Node.js — verify the signature before trusting a delivery
import crypto from "crypto";
function verify(rawBody, signature, secret) {
const expected = crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}Delivery, retries and the test event
Reply with any 2xx status to acknowledge a delivery. If your endpoint errors or times out, we keep the leads and try again on the next pass; after repeated failures the webhook is paused automatically so a broken URL does not pile up. Use the Test button in the dashboard to send a signed ping event and confirm your endpoint is wired up before you rely on it.
Ready to build? Create your key in the dashboard.
Open the dashboard
fisher