REST API and webhooks

Scrape.Email developer reference

Everything the workspace can do is available to your code: search and export the lead catalog, enrich public URLs, run Instant Scrape jobs in the cloud, read saved leads, pull music-promotion and press contacts, and receive signed account events. Jobs keep running on the server after your process exits, so integrations can run unattended.

OpenAPI 3.1 spec Postman collection TypeScript SDK: npm i scrape-email

Authentication and scopes

Create an account-scoped key in the signed-in API & Webhooks module. The full key is shown once. Send it only from server-side code.

Search permits search and saved-lead reads.

Export permits CSV export delivery.

Webhook identifies keys intended for integration administration; webhook destinations themselves are managed in the workspace.

Authorization: Bearer bl_live_...
Content-Type: application/json

Base URL: https://www.scrape.email

CSV export

POST /api/v1/leads/export requires the Export scope. Use the same search filters plus quantity for the number of matching rows to reveal. Delivery is bounded by matching rows and remaining account credits.

The response is UTF-8 CSV with Content-Disposition. Usage and save totals are returned in X-Lead-* response headers. Spreadsheet-formula prefixes are neutralized before export.

curl -X POST https://www.scrape.email/api/v1/leads/export \
  -H "Authorization: Bearer bl_live_..." \
  -H "Content-Type: application/json" \
  -o verified-software-leads.csv \
  -d '{
    "industry": "Computer Software",
    "verification": "Yes",
    "quantity": 5000
  }'

Saved leads

GET /api/v1/leads/saved requires the Search scope and returns only contacts already revealed in this account workspace. Reading saved contacts does not spend credits.

Query parameters: page 1-10000, pageSize 1-200, optional status, and optional campaignId.

curl "https://www.scrape.email/api/v1/leads/saved?page=1&pageSize=100&status=Saved" \
  -H "Authorization: Bearer bl_live_..."

{
  "rows": [ ... ],
  "total": 240,
  "page": 1,
  "pageSize": 100
}

Account and credits

GET /api/v1/account requires the Search scope. It returns the workspace, plan, live credit balance, and the credit cost of every module so your integration can budget before it reveals anything.

curl https://www.scrape.email/api/v1/account   -H "Authorization: Bearer bl_live_..."

{
  "workspace": "Acme Growth",
  "plan": "Professional",
  "usage": { "creditLimit": 150000, "creditsUsed": 4200, "creditsRemaining": 145800 },
  "creditCosts": {
    "leadFinder": 1, "urlEnrichment": 5,
    "musicPromotion": 5, "press": 5, "instantScrape": 20
  }
}

Email verification

POST /api/v1/verify requires the Search scope and accepts one address or up to 100 per call. It checks syntax, domain, the mail exchanger, disposable mailboxes, role addresses, free providers, common misspellings, and catalog readiness. The cost is 1 credit per verified address; only the affordable share of a batch runs and the remainder is returned in skipped.

A misspelled domain returns a suggestion so you can correct it before sending. invalid and disposable addresses should be removed from a send list; risky addresses are deliverable but personal or shared.

curl -X POST https://www.scrape.email/api/v1/verify   -H "Authorization: Bearer bl_live_..."   -H "Content-Type: application/json"   -d '{ "emails": ["jane@company.com", "sales@gmial.com"] }'

{
  "rows": [{
    "email": "sales@gmial.com",
    "status": "invalid",
    "reason": "The domain looks like a misspelling of a major provider.",
    "suggestion": "sales@gmail.com",
    "score": 20,
    "checks": { "syntax": true, "mx": false, "typo": true }
  }],
  "summary": { "total": 2, "valid": 1, "invalid": 1 },
  "creditsCharged": 2
}

Free signup and account deletion

POST /api/v1/register is public — no key required. It creates a 14-day trial workspace with 20 free credits and returns a working API key straight away, which is how the mobile app onboards new users. It is throttled per IP because every signup carries free credits.

POST /api/v1/account/delete is the self-service deletion path: send your key and { "confirm": true } to remove the account and all of its data. Payment records are retained for accounting. Deletion is also available at /delete-account.

# Create a free account (no key needed)
curl -X POST https://www.scrape.email/api/v1/register   -H "Content-Type: application/json"   -d '{ "name": "Alex Morgan", "email": "alex@company.com", "password": "at-least-eight" }'

# → { "apiKey": "bl_live_...", "account": { "plan": "Trial", "usage": { "creditsRemaining": 20 } } }

# Delete the account and all of its data
curl -X POST https://www.scrape.email/api/v1/account/delete   -H "Authorization: Bearer bl_live_..."   -H "Content-Type: application/json"   -d '{ "confirm": true }'

URL enrichment

POST /api/v1/enrichment requires the Search scope and accepts up to 100 public URLs per call. It returns the brand-owned contact routes found on each page: all emails, all phone numbers, social usernames, per-network profile URLs, the contact page, and the submission link. Off-brand social accounts, paid pitch platforms, and unrelated submission links are removed automatically. Only URLs that return contact details are charged, at 5 credits each.

curl -X POST https://www.scrape.email/api/v1/enrichment   -H "Authorization: Bearer bl_live_..."   -H "Content-Type: application/json"   -d '{ "urls": ["https://example.com", "https://another.com"] }'
{
  "rows": [{
    "inputUrl": "https://example.com",
    "status": "enriched",
    "company": "Example",
    "emails": ["hello@example.com"],
    "phones": ["+1 555 0100"],
    "socialUsernames": ["@example · Instagram"],
    "contactPage": "https://example.com/contact",
    "submissionLink": "",
    "socialProfiles": ["https://www.instagram.com/example/"]
  }],
  "creditsCharged": 5,
  "contactDetailsFound": 1
}

Emits enrichment.completed.

Instant Scrape — asynchronous jobs

Instant Scrape is asynchronous. POST /api/v1/scrape/jobs accepts a URL list, queues it, and returns immediately. A server-side worker then keeps advancing the job batch by batch even if your process exits, the container restarts, or nobody is watching the dashboard. Your integration can simply wait for the scrape.job.completed webhook instead of polling.

# 1. Queue a job (Search scope)
curl -X POST https://www.scrape.email/api/v1/scrape/jobs   -H "Authorization: Bearer bl_live_..."   -H "Content-Type: application/json"   -d '{ "text": "https://www.instagram.com/natgeo/" }'

# 2. Optional: check progress (Search scope)
curl "https://www.scrape.email/api/v1/scrape/jobs/{jobId}?offset=0&limit=200"   -H "Authorization: Bearer bl_live_..."

# 3. Download the finished CSV (Export scope)
curl -o scrape-job.csv   "https://www.scrape.email/api/v1/scrape/jobs/{jobId}/export"   -H "Authorization: Bearer bl_live_..."

POST /api/v1/scrape/jobs returns the job id with usage and skipped counts. Each successful enriched result costs 20 credits; failed inputs and unsupported URLs are refunded or never charged.

GET /api/v1/scrape/jobs → the 50 most recent jobs for the account.

GET /api/v1/scrape/jobs/{jobId} → job progress plus result rows, paged with offset and limit (max 2,000).

GET /api/v1/scrape/jobs/{jobId}/export → UTF-8 CSV of the results, with X-Scrape-Rows.

Emits scrape.job.created and scrape.job.completed.

Music promotion

POST /api/v1/music-promotion/search requires the Search scope; POST /api/v1/music-promotion/export requires Export. Both accept the same filters as the workspace module: playlist, radio, TV, network, podcast, DJ, label, PR, booking, venue, and media records, with country, region, city, genre, audience market, contact route, and qualification filters. Each newly delivered canonical contact costs 5 credits and is saved once.

curl -X POST https://www.scrape.email/api/v1/music-promotion/search   -H "Authorization: Bearer bl_live_..."   -H "Content-Type: application/json"   -d '{
    "query": "college radio",
    "country": "United States",
    "contactMethod": "email",
    "pageSize": 50
  }'

Press and journalists

POST /api/v1/press/search requires the Search scope; POST /api/v1/press/export requires Export. Filter by category, outlet type, country, contact route, email status, email evidence, or source provenance. Each newly delivered contact costs 5 credits.

curl -X POST https://www.scrape.email/api/v1/press/search   -H "Authorization: Bearer bl_live_..."   -H "Content-Type: application/json"   -d '{
    "category": "Technology & Software",
    "country": "United Kingdom",
    "contactMethod": "email",
    "pageSize": 50
  }'

Suppression sync

Keep your do-not-contact list aligned with ours. A suppression added here is excluded from every send path, including scheduled follow-ups, and checked again immediately before delivery. Sync a suppression from your CRM so nothing is ever emailed twice.

GET /api/v1/suppressions reads the list, POST adds one or many with a reason and source, and DELETE ?email= removes an entry. All three require the Search scope.

# Read the list
curl https://www.scrape.email/api/v1/suppressions?limit=500   -H "Authorization: Bearer bl_live_..."

# Add one, or many in a single call
curl -X POST https://www.scrape.email/api/v1/suppressions   -H "Authorization: Bearer bl_live_..."   -H "Content-Type: application/json"   -d '{ "emails": ["a@x.com", "b@y.com"], "reason": "Unsubscribed", "source": "Provider" }'

# Remove an entry
curl -X DELETE "https://www.scrape.email/api/v1/suppressions?email=a@x.com"   -H "Authorization: Bearer bl_live_..."

Signed webhooks

Register an HTTPS destination in the workspace and subscribe to any of: search.completed, export.completed, lead.created, enrichment.completed, scrape.job.created, scrape.job.completed, music-promotion.completed, and press.completed. Each delivery uses a unique event ID. Failed deliveries are attempted up to three times; a destination pauses after five failed delivery cycles.

Event payloads

EventFired whendata
search.completedA lead search delivered contactsdelivered, total, page, pageSize, matchMode, creditsRemaining
export.completedA CSV export finished or a scrape CSV was downloadedrowCount, saved, existing, creditsRemaining, jobId, source
lead.createdNew canonical contacts were saved to the workspacecount, source
enrichment.completedURL enrichment finishedsubmitted, contactDetailsFound, contactDetailsLocked, creditsCharged, creditsRemaining
scrape.job.createdAn Instant Scrape job was queuedjobId, datasetId, inputCount, totalBatches, skipped, creditsRemaining
scrape.job.completedThe cloud worker finished a scrape jobjobId, inputs, success, failed, creditsUsed
music-promotion.completedA music-promotion reveal delivered contactsdelivered, total, creditsCharged, creditsRemaining, source
press.completedA press reveal delivered contactsdelivered, total, creditsCharged, creditsRemaining, source
X-Scrape-Email-Event: search.completed
X-Scrape-Email-Signature: t=1700000000,v1=<hex digest>
Content-Type: application/json

{
  "id": "evt_...",
  "event": "search.completed",
  "timestamp": 1700000000,
  "data": { ... }
}

Compute HMAC-SHA256 with the signing secret over timestamp + "." + rawBody, then compare it to v1 using a constant-time comparison.

Reject stale timestamps and store processed event IDs to prevent replay.

Return a 2xx response quickly, then process the accepted event asynchronously.

Rotate a signing secret from the workspace when exposure is suspected; the previous value stops working immediately.

Errors, usage, and rate limits

HTTPMeaning
400Invalid JSON, filter, page, page size, or export quantity.
401The Bearer key is missing, invalid, revoked, or lacks the required scope.
402The account has no remaining credits for this delivery.
429The per-key endpoint limit was exceeded. Honor Retry-After.
503The catalog or delivery service is temporarily unavailable.

Per API key: search permits 60 requests per minute, export 10, saved-lead reads 120, account reads 120, enrichment 30, music and press search 30, instant-scrape creation 20, and instant-scrape status 240. Successful and rate-limited responses include RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset. A 429 also includes Retry-After. Use exponential backoff for 429 and transient 503 responses; do not automatically retry validation or credit errors.

SDKs and generated clients

Every client is generated from the same OpenAPI contract, so the SDKs cannot drift from the API. The first-party TypeScript SDK ships the typed client plus a webhook signature verifier; other languages can be generated from the spec with openapi-generator.

# Official TypeScript SDK
npm install scrape-email

// or generate a client for any language
npx @openapitools/openapi-generator-cli generate   -i https://www.scrape.email/openapi.json   -g python -o ./clients/python
import { ScrapeEmail } from "scrape-email";

const client = new ScrapeEmail({ apiKey: process.env.KEY! });

const { rows, usage } = await client.searchLeads({
  industry: "Computer Software",
  country: "Canada",
  pageSize: 100,
});

const { job } = await client.createScrapeJob(urls);
const done = await client.waitForScrapeJob(job.id);

Need implementation help?

Use Help for workflow guidance or open API & Webhooks after signing in to create credentials and test a destination.