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.
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.
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.
Rate limits
Limits are per account (all your keys together) and per minute. They protect the service and never use credits.
| Requests | Per minute | Endpoints |
|---|---|---|
| Submit and delete | 30 | POST /v1/jobs, DELETE /v1/jobs/{id} |
| Reads | 120 | GET /v1/account, /v1/tools, /v1/jobs, /v1/jobs/{id} |
| Downloads | 60 | GET /v1/jobs/{id}/result |
Over a limit, the API answers 429 with a Retry-After header: the seconds to wait before retrying.
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.
| charged_per | Meaning |
|---|---|
delivered_row | Each row delivered in the result. |
successful_result | Each successful result. Waterfall Enrich: each email found; rows where no email is found use no credits. |
processed_row | Each 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.
| status | Meaning |
|---|---|
submitted | Received and waiting to start. Credits are reserved. |
in_progress | Being processed by Prospectal. |
completed | The result is ready to download. Credits are charged and any unused reservation is released. |
# 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.
| tool | Input | Rate | Min. rows | Splitting above |
|---|---|---|---|---|
sales-navigator | URL | 1 per delivered_row | 500 | 2,500 rows |
sales-navigator-accounts | URL | 1 per delivered_row | 500 | 1,000 rows |
company-followers | URL | 1 per delivered_row | 500 | — |
linkedin-group | URL | 1 per delivered_row | 500 | — |
post-engagers | URL | 3 per delivered_row | 500 | — |
apollo | URL | 1 per delivered_row | 500 | — |
waterfall-enrich | File | 3 per successful_result | 1 | — |
email-verify | File | 0.5 per processed_row | 1 | — |
linkedin-url-enrich | File | 3 per successful_result | 1 | — |
company-website-finder | File | 3 per successful_result | 1 | — |
Email options
The people scrapers include the email when it is available, at no extra charge. One optional service, off by default: Verify Emails.
| Option | Rate | Where |
|---|---|---|
verify_emails | 0.5 credit per email verified | Sales 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. |
| Tool | Email included | verify_emails |
|---|---|---|
| Sales Navigator Leads | Yes, when available | Yes |
| Sales Navigator Accounts | No | No |
| Company Followers | Yes, when available | Yes |
| LinkedIn Group | Yes, when available | Yes |
| Post Engagers | Yes, when available | Yes |
| Apollo | Yes, when available | Yes |
| LinkedIn URL Enrich | Yes, when available | Yes |
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.
Smart Link Splitting
Smart Link Splitting applies to Sales Navigator Leads above 2,500 rows and Sales Navigator Accounts above 1,000 rows. It is included with the Agency, Scale and Custom packages. On other packages, a larger requested_count on those two tools returns 403 smart_link_splitting_required and nothing is reserved: lower the count or upgrade. The API never splits a search silently.
Results: Valid / Invalid
Email verification has two results only: Valid or Invalid. An email that can’t be confirmed is Invalid. Both are charged.
| Project | Result file |
|---|---|
| Email Verify | Every 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. |
| Scraper | The scraped rows, with the Email column filled where an email is available. No verification column. |
| Scraper with verify_emails | The 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.
curl "$API_BASE/v1/account" \ -H "Authorization: Bearer $PROSPECTAL_API_KEY"
{
"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.
curl "$API_BASE/v1/tools" \ -H "Authorization: Bearer $PROSPECTAL_API_KEY"
{
"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.
| Parameter | Type | Required | Description |
|---|---|---|---|
tool | string | Yes | A tool from GET /v1/tools with input "input_url". |
project_name | string | Yes | Your name for the project. |
input_url | string | Yes | The full search or page URL. |
requested_count | integer | Yes | Rows to deliver. At least the tool’s minimum_rows (500 for scrapers). |
description | string | No | A note for the project. |
verify_emails | boolean | No | Verify the emails that come with the results, Valid or Invalid. Default false. |
find_emails | boolean | No | Not offered by any tool; true returns 400 option_not_available. |
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}'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.
| Parameter | Type | Required | Description |
|---|---|---|---|
file | file | Yes | A .csv or .xlsx file, up to 20 MB. |
tool | string | Yes | A tool from GET /v1/tools with input "file". |
project_name | string | Yes | Your name for the project. |
requested_count | integer | No | For a CSV, defaults to the number of data rows (header excluded). Required for an XLSX. |
description | string | No | A note for the project. |
curl "$API_BASE/v1/jobs" \ -H "Authorization: Bearer $PROSPECTAL_API_KEY" \ -F tool=email-verify \ -F project_name="March list" \ -F file=@emails.csv
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.
| Parameter | Type | Required | Description |
|---|---|---|---|
status | string | No | submitted, in_progress or completed. |
limit | integer | No | 1–100. Default 25. |
created_before | string | No | An ISO 8601 time. |
curl "$API_BASE/v1/jobs?status=completed&limit=50" \ -H "Authorization: Bearer $PROSPECTAL_API_KEY"
{
"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.
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | The project id. |
curl "$API_BASE/v1/jobs/JOB_ID" \ -H "Authorization: Bearer $PROSPECTAL_API_KEY"
{ "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.
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | The project id. |
curl "$API_BASE/v1/jobs/JOB_ID/result" \ -H "Authorization: Bearer $PROSPECTAL_API_KEY"
{
"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.
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | The project id. |
curl -X DELETE "$API_BASE/v1/jobs/JOB_ID" \ -H "Authorization: Bearer $PROSPECTAL_API_KEY"
{ "job": { "id": "…", "credits": { "reserved": 1000, "charged": 1000, "released": 0 }, … } }Errors
Every error has a stable error code and a readable message.
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 | HTTP | message |
|---|---|---|
not_authenticated | 401 | A valid API key is required. |
invalid_request | 400 | The request could not be read. |
unknown_tool | 400 | Unknown tool. See GET /v1/tools. |
tool_unavailable | 422 | This tool is not taking new projects. |
invalid_count | 400 | requested_count must be a whole number greater than 0. |
project_name_required | 400 | project_name is required. |
invalid_url | 400 | input_url must be a full URL, e.g. https://www.linkedin.com/… |
invalid_file | 400 | The input file is missing or could not be attached. |
invalid_file_type | 415 | The file must be a .csv or .xlsx file. |
empty_file | 400 | The file is empty. |
file_too_large | 413 | Files up to 20 MB can be sent through the API. Upload larger files in the Prospectal app. |
file_already_used | 409 | This file is already attached to another job. |
minimum_rows | 422 | requested_count is below this tool's minimum (see GET /v1/tools). |
insufficient_credits | 402 | Not enough available credits for this job. |
option_not_available | 400 | This tool does not offer that option. See find_emails / verify_emails in GET /v1/tools. |
verify_requires_find_emails | 400 | verify_emails needs find_emails on this tool (it verifies the emails found). |
smart_link_splitting_required | 403 | This 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_key | 400 | Idempotency-Key must be at most 255 characters. |
idempotency_conflict | 409 | A request with this Idempotency-Key is already being processed. Retry shortly. |
job_not_found | 404 | Job not found. |
job_already_deleted | 404 | Job not found. |
reservation_mismatch | 409 | This job could not be deleted. Please contact support. |
not_completed | 409 | The job is not completed yet. |
file_expired | 410 | The result is no longer available after the 30-day retention period. |
not_found | 404 | Unknown endpoint. |
method_not_allowed | 405 | This method is not allowed on this endpoint. |
rate_limited | 429 | Too many requests. Retry after the number of seconds in the Retry-After header. |
storage_unavailable | 503 | File storage is unavailable. Retry shortly. |
internal_error | 500 | Something went wrong. |