Skip to content
Prospectal

Prospectal REST API

Submit projects, follow them and download the results from your own code. The API uses your Prospectal account: the same credit balance, tool rates, minimums and projects as the app.

Create API Key

New to Prospectal? Get Started

Format
JSON over HTTPS
Auth
API key (Bearer)
Results
Polling, no webhooks
Uploads
CSV / XLSX up to 20 MB

Introduction

The base URL for every request is https://uuzawgjsghowrfgfblha.supabase.co/functions/v1/api. Paths start with /v1.

Projects you submit through the API appear in your Prospectal dashboard, and projects from the app appear in the API. The API is polling-based: you check a project until it is completed, then download the result. There are no webhooks.

Every response is JSON. Errors return { "error", "message" } with an HTTP status; see Errors below.

Setup
export API_BASE="https://uuzawgjsghowrfgfblha.supabase.co/functions/v1/api"
export PROSPECTAL_API_KEY="psk_live_…"   # from Settings → API keys

curl "$API_BASE/v1/account" \
  -H "Authorization: Bearer $PROSPECTAL_API_KEY"

Authentication

Send your API key in the Authorization header as Bearer psk_live_…. The X-API-Key header is also accepted.

Create keys in the Prospectal app under Settings → API keys. A key is shown once, when you create it; only its first characters are kept for display, so store it safely. You can have up to 5 active keys and revoke any key at once. A key acts as your account, so keep it secret and never put it in client-side code.

Create API Key

Rate limits

Limits are per account (all your keys together) and per minute. They protect the service and never use credits.

Rate limits
RequestsPer minuteEndpoints
Submit and delete30POST /v1/jobs, DELETE /v1/jobs/{id}
Reads120GET /v1/account, /v1/tools, /v1/jobs, /v1/jobs/{id}
Downloads60GET /v1/jobs/{id}/result

Over a limit, the API answers 429 with a Retry-After header: the seconds to wait before retrying.

Over the limit
429 Too Many Requests
Retry-After: 18

{
  "error": "rate_limited",
  "message": "Too many requests. Retry after the number of seconds in the Retry-After header.",
  "retry_after": 18
}

Credits

The API spends the same Prospectal Credits as the app, at each tool’s rate. When a project is accepted, its maximum cost is reserved: requested_count × (the tool’s rate + each selected option’s rate). When it completes, you are charged for what was delivered, found and verified, and the rest of the reservation is released.

Deleting a Submitted or In Progress project charges its full reservation, selected options included. Deleting a Completed project changes no credits.

What is charged
charged_perMeaning
delivered_rowEach row delivered in the result.
successful_resultEach successful result. Waterfall Enrich: each email found; rows where no email is found use no credits.
processed_rowEach row processed. Email Verify: every email processed, whether it comes back Valid or Invalid.

Polling workflow

Submit a project, then read it with GET /v1/jobs/{id} until its status is completed. Keep polling within the read limit; once a minute is plenty. Then ask for a download link: each link works for 5 minutes, and results are kept for 30 days.

Project statuses
statusMeaning
submittedReceived and waiting to start. Credits are reserved.
in_progressBeing processed by Prospectal.
completedThe result is ready to download. Credits are charged and any unused reservation is released.
Submit, poll, download
# 1. Submit
curl "$API_BASE/v1/jobs" \
  -H "Authorization: Bearer $PROSPECTAL_API_KEY" \
  -F tool=email-verify -F project_name="March list" -F file=@emails.csv

# 2. Poll until "status": "completed" (reads: 120 per minute)
curl "$API_BASE/v1/jobs/JOB_ID" \
  -H "Authorization: Bearer $PROSPECTAL_API_KEY"

# 3. Get a 5-minute download link, then download the file
curl "$API_BASE/v1/jobs/JOB_ID/result" \
  -H "Authorization: Bearer $PROSPECTAL_API_KEY"

Idempotency-Key

Send an Idempotency-Key header (up to 255 characters) with POST /v1/jobs to make retries safe: repeating the same key returns the first project instead of creating a second one, and nothing is reserved twice. While the first request is still being processed, a repeat gets 409 idempotency_conflict; retry shortly.

Tools and rates

GET /v1/tools returns these from the live rates. URL tools take input_url; file tools take a CSV or XLSX upload.

Tools, rates and minimums
toolInputRateMin. rowsSplitting above
sales-navigatorURL1 per delivered_row5002,500 rows
sales-navigator-accountsURL1 per delivered_row5001,000 rows
company-followersURL1 per delivered_row500—
linkedin-groupURL1 per delivered_row500—
post-engagersURL3 per delivered_row500—
apolloURL1 per delivered_row500—
waterfall-enrichFile3 per successful_result1—
email-verifyFile0.5 per processed_row1—
linkedin-url-enrichFile3 per successful_result1—
company-website-finderFile3 per successful_result1—

Email options

The people scrapers include the email when it is available, at no extra charge. One optional service, off by default: Verify Emails.

Email options
OptionRateWhere
verify_emails0.5 credit per email verifiedSales Navigator Leads, Company Followers, LinkedIn Group, Post Engagers, Apollo and LinkedIn URL Enrich. Verifies the emails that come with the results; each email is marked Valid or Invalid, and both are charged.
find_emails—Not offered by any tool: the email comes with the results when it is available (email_included in GET /v1/tools). Sending true returns 400 option_not_available.
Email options by tool
ToolEmail includedverify_emails
Sales Navigator LeadsYes, when availableYes
Sales Navigator AccountsNoNo
Company FollowersYes, when availableYes
LinkedIn GroupYes, when availableYes
Post EngagersYes, when availableYes
ApolloYes, when availableYes
LinkedIn URL EnrichYes, when availableYes

Asking for an option a tool does not offer — find_emails on any tool, or verify_emails on one without emails — returns 400 option_not_available, before anything is reserved.

Results: Valid / Invalid

Email verification has two results only: Valid or Invalid. An email that can’t be confirmed is Invalid. Both are charged.

What the result file contains
ProjectResult file
Email VerifyEvery processed email, each with an Email Verification value of Valid or Invalid. Invalid emails are marked, not removed: 1,000 emails in means 1,000 rows back.
ScraperThe scraped rows, with the Email column filled where an email is available. No verification column.
Scraper with verify_emailsThe scraped rows, with Email Verification set to Valid or Invalid for each email. Rows without an email leave Email Verification blank.

GET/v1/account

Your account

Your Prospectal Credits: available to spend, and reserved by projects that are not completed yet. Also your package tier and whether Smart Link Splitting is included.

Request
curl "$API_BASE/v1/account" \
  -H "Authorization: Bearer $PROSPECTAL_API_KEY"
Response
{
  "email": "you@company.com",
  "credits": { "available": 10000.5, "reserved": 1000 },
  "package_tier": "agency",
  "smart_link_splitting": true
}

GET/v1/tools

Tools, rates and options

Every tool you can submit to: its input (input_url or file), its rate in credits per result, what is charged, its minimum rows, the rows above which a Sales Navigator search needs Smart Link Splitting, and which email options it offers. "options" gives the option rates.

Request
curl "$API_BASE/v1/tools" \
  -H "Authorization: Bearer $PROSPECTAL_API_KEY"
Response
{
  "tools": [
    { "tool": "sales-navigator", "input": "input_url", "credits_per_result": 1, "charged_per": "delivered_row",
      "minimum_rows": 500, "smart_link_splitting_above_rows": 2500,
      "find_emails": false, "email_included": true, "verify_emails": true },
    { "tool": "apollo", "input": "input_url", "credits_per_result": 1, "charged_per": "delivered_row",
      "minimum_rows": 500, "smart_link_splitting_above_rows": null,
      "find_emails": false, "email_included": true, "verify_emails": true },
    { "tool": "email-verify", "input": "file", "credits_per_result": 0.5, "charged_per": "processed_row",
      "minimum_rows": 1, "smart_link_splitting_above_rows": null,
      "find_emails": false, "email_included": false, "verify_emails": false },
    …
  ],
  "options": {
    "find_emails": null,
    "verify_emails": { "credits_per_email_verified": 0.5, "results": ["Valid", "Invalid"] }
  }
}

POST/v1/jobs

Submit a project (URL tools)

For the scrapers. Send JSON. The most the project can cost — requested_count × the tool’s rate, plus Verify Emails if on — is reserved from your balance when the project is accepted.

POST /v1/jobs parameters
ParameterTypeRequiredDescription
toolstringYesA tool from GET /v1/tools with input "input_url".
project_namestringYesYour name for the project.
input_urlstringYesThe full search or page URL.
requested_countintegerYesRows to deliver. At least the tool’s minimum_rows (500 for scrapers).
descriptionstringNoA note for the project.
verify_emailsbooleanNoVerify the emails that come with the results, Valid or Invalid. Default false.
find_emailsbooleanNoNot offered by any tool; true returns 400 option_not_available.
Request
curl "$API_BASE/v1/jobs" \
  -H "Authorization: Bearer $PROSPECTAL_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: q4-leads-1" \
  -d '{"tool":"sales-navigator","project_name":"Q4 leads","input_url":"https://www.linkedin.com/sales/search/people?…","requested_count":1000}'
Response
201 Created
{ "job": {
    "id": "4f1c…",
    "tool": "sales-navigator",
    "project_name": "Q4 leads",
    "description": null,
    "status": "submitted",
    "requested_count": 1000,
    "delivered_count": null,
    "billable_count": null,
    "rate": { "credits_per_result": 1, "charged_per": "delivered_row" },
    "credits": { "reserved": 1000, "charged": null, "released": null },
    "options": { "find_emails": false, "verify_emails": false, "credits_per_email_found": null, "credits_per_email_verified": null },
    "emails": null,
    "input": { "url": "https://www.linkedin.com/sales/search/people?…" },
    "result": null,
    "created_at": "2026-10-14T10:00:00Z",
    "started_at": null,
    "completed_at": null
  } }

POST/v1/jobs

Submit a project (Bulk CSV)

For the file tools (Waterfall Enrich, Email Verify, LinkedIn URL Enrich, Company Website Finder). Send multipart/form-data with the CSV or XLSX in the "file" field. Files up to 20 MB; upload larger files in the Prospectal app.

POST /v1/jobs parameters
ParameterTypeRequiredDescription
filefileYesA .csv or .xlsx file, up to 20 MB.
toolstringYesA tool from GET /v1/tools with input "file".
project_namestringYesYour name for the project.
requested_countintegerNoFor a CSV, defaults to the number of data rows (header excluded). Required for an XLSX.
descriptionstringNoA note for the project.
Request
curl "$API_BASE/v1/jobs" \
  -H "Authorization: Bearer $PROSPECTAL_API_KEY" \
  -F tool=email-verify \
  -F project_name="March list" \
  -F file=@emails.csv
Response
201 Created
{ "job": { "id": "…", "tool": "email-verify", "status": "submitted",
           "requested_count": 1000,
           "credits": { "reserved": 500, "charged": null, "released": null },
           "input": { "filename": "emails.csv" }, … } }

GET/v1/jobs

List projects

Newest first, including projects submitted in the app. When next_created_before is not null, pass it as created_before for the next page.

GET /v1/jobs parameters
ParameterTypeRequiredDescription
statusstringNosubmitted, in_progress or completed.
limitintegerNo1–100. Default 25.
created_beforestringNoAn ISO 8601 time.
Request
curl "$API_BASE/v1/jobs?status=completed&limit=50" \
  -H "Authorization: Bearer $PROSPECTAL_API_KEY"
Response
{
  "jobs": [ { "id": "…", "status": "completed", … } ],
  "next_created_before": null
}

GET/v1/jobs/{id}

One project

Poll this until status is completed. A completed project with Find or Verify Emails has "emails": found, verified, valid and invalid counts.

GET /v1/jobs/{id} parameters
ParameterTypeRequiredDescription
idstringYesThe project id.
Request
curl "$API_BASE/v1/jobs/JOB_ID" \
  -H "Authorization: Bearer $PROSPECTAL_API_KEY"
Response
{ "job": { "id": "4f1c…", "tool": "email-verify", "status": "completed",
  "requested_count": 1000, "delivered_count": 1000,
  "credits": { "reserved": 500, "charged": 500, "released": 0 }, … } }

GET/v1/jobs/{id}/result

Download the result

A new download link for a completed project, valid for 5 minutes. Ask again whenever you need one; results are kept for 30 days.

GET /v1/jobs/{id}/result parameters
ParameterTypeRequiredDescription
idstringYesThe project id.
Request
curl "$API_BASE/v1/jobs/JOB_ID/result" \
  -H "Authorization: Bearer $PROSPECTAL_API_KEY"
Response
{
  "url": "https://…",
  "filename": "emails-verified.csv",
  "expires_in": 300
}

DELETE/v1/jobs/{id}

Delete a project

As in the app: deleting a Submitted or In Progress project charges its full reservation, selected options included, and refunds nothing. Deleting a Completed project changes no credits.

DELETE /v1/jobs/{id} parameters
ParameterTypeRequiredDescription
idstringYesThe project id.
Request
curl -X DELETE "$API_BASE/v1/jobs/JOB_ID" \
  -H "Authorization: Bearer $PROSPECTAL_API_KEY"
Response
{ "job": { "id": "…", "credits": { "reserved": 1000, "charged": 1000, "released": 0 }, … } }

Errors

Every error has a stable error code and a readable message.

Error response
413 Payload Too Large
{
  "error": "file_too_large",
  "message": "Files up to 20 MB can be sent through the API. Upload larger files in the Prospectal app."
}
Error codes
errorHTTPmessage
not_authenticated401A valid API key is required.
invalid_request400The request could not be read.
unknown_tool400Unknown tool. See GET /v1/tools.
tool_unavailable422This tool is not taking new projects.
invalid_count400requested_count must be a whole number greater than 0.
project_name_required400project_name is required.
invalid_url400input_url must be a full URL, e.g. https://www.linkedin.com/…
invalid_file400The input file is missing or could not be attached.
invalid_file_type415The file must be a .csv or .xlsx file.
empty_file400The file is empty.
file_too_large413Files up to 20 MB can be sent through the API. Upload larger files in the Prospectal app.
file_already_used409This file is already attached to another job.
minimum_rows422requested_count is below this tool's minimum (see GET /v1/tools).
insufficient_credits402Not enough available credits for this job.
option_not_available400This tool does not offer that option. See find_emails / verify_emails in GET /v1/tools.
verify_requires_find_emails400verify_emails needs find_emails on this tool (it verifies the emails found).
smart_link_splitting_required403This search needs Smart Link Splitting, included with the Agency, Scale and Custom packages. Lower requested_count to the tool's smart_link_splitting_above_rows (GET /v1/tools) or upgrade your package.
invalid_idempotency_key400Idempotency-Key must be at most 255 characters.
idempotency_conflict409A request with this Idempotency-Key is already being processed. Retry shortly.
job_not_found404Job not found.
job_already_deleted404Job not found.
reservation_mismatch409This job could not be deleted. Please contact support.
not_completed409The job is not completed yet.
file_expired410The result is no longer available after the 30-day retention period.
not_found404Unknown endpoint.
method_not_allowed405This method is not allowed on this endpoint.
rate_limited429Too many requests. Retry after the number of seconds in the Retry-After header.
storage_unavailable503File storage is unavailable. Retry shortly.
internal_error500Something went wrong.