Prospect API
Bearer credentials with explicit scopes, mandatory idempotency keys on every mutation, and a request id on every response.
Bearer credentials, created on the API credentials page in the app. The secret is shown once.
curl -s -H 'Authorization: Bearer pxk_xxxxxxxx_…' \
'https://prospex.ch/api/v1/prospect/projects'
Every response carries request_id in the body and in X-Request-Id, plus X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. Every call is recorded in your project's audit history with the credential name and that request id.
Scopes
| Scope | Permits |
|---|---|
| prospect:read | Read projects and prospects |
| prospect:write | Add companies and record decisions |
| prospect:run | Start cycles and request research |
| prospect:stages | Read, claim and complete external stage jobs |
| prospect:approve | Approve a named outreach revision |
| prospect:outcomes | Record downstream outcomes (published, but no route accepts it yet) |
| webhooks:manage | Manage webhook endpoints (published, but no route accepts it yet) |
| companies:read | Search the Swiss company directory |
| markets:read | Read your markets and their companies |
| watches:read | Read your watches and their signals |
Approving is a scope of its own because it releases customer-facing copy into downstream work: a read or run credential cannot approve a bundle. prospect:stages permits reading, claiming and completing configured external stage jobs.
Routes
| Name | Path |
|---|---|
| cycle_create | /api/v1/prospect/projects/<str:project_id>/cycles |
| cycle_detail | /api/v1/prospect/projects/<str:project_id>/cycles/<str:cycle_id> |
| project_detail | /api/v1/prospect/projects/<str:project_id> |
| project_list | /api/v1/prospect/projects |
| prospect_approvals | /api/v1/prospect/projects/<str:project_id>/prospects/<str:prospect_id>/approvals |
| prospect_decisions | /api/v1/prospect/projects/<str:project_id>/prospects/<str:prospect_id>/decisions |
| prospect_detail | /api/v1/prospect/projects/<str:project_id>/prospects/<str:prospect_id> |
| prospect_research | /api/v1/prospect/projects/<str:project_id>/prospects/<str:prospect_id>/research |
| prospects | /api/v1/prospect/projects/<str:project_id>/prospects |
| stage_job_cancellations | /api/v1/prospect/projects/<str:project_id>/stage-jobs/<str:job_id>/cancellations |
| stage_job_claims | /api/v1/prospect/projects/<str:project_id>/stage-jobs/<str:job_id>/claims |
| stage_job_detail | /api/v1/prospect/projects/<str:project_id>/stage-jobs/<str:job_id> |
| stage_job_failures | /api/v1/prospect/projects/<str:project_id>/stage-jobs/<str:job_id>/failures |
| stage_job_list | /api/v1/prospect/projects/<str:project_id>/stage-jobs |
| stage_job_results | /api/v1/prospect/projects/<str:project_id>/stage-jobs/<str:job_id>/results |
| stage_job_retries | /api/v1/prospect/projects/<str:project_id>/stage-jobs/<str:job_id>/retries |
Project creation and offering editing stay in the browser.
.../research requests research using the project's configured executor. External output enters only through a named stage job's /results, which binds it to the right input snapshot and upstream revisions.
Mutations
- Every mutation needs an
Idempotency-Keyheader. - The same key with the same request returns the original response byte for byte, with
Idempotency-Replayed: true, and spends no second research unit. - The same key with a different request answers 422
idempotency_conflict. - Work that runs in the background answers
202with the cycle. - Starting a cycle when one is already queued or running answers
200with that cycle when your request names no new prospects. Naming new prospects answers409with the blocking cycle attached. - Adding companies resolves identity and consumes no research unit. At most 100 per request.
- An ambiguous identity comes back as a structured resolution with the candidates.
- Approving names both the outreach revision and the content fingerprint you reviewed. A fingerprint that belongs to a different revision is refused.
10,000 requests per account per day.
Errors
{
"error": {
"code": "validation_failed",
"message": "…",
"errors": [{"code": "evidence_reference_missing", "field": "claims[1].evidence_ids", "detail": "…"}]
},
"request_id": "req_…"
}
| Status | code | When |
|---|---|---|
| 400 | invalid_parameter | A parameter was understood and its value refused. |
| 400 | invalid_request | The body or a parameter could not be read. |
| 400 | unknown_parameter | A parameter this route does not accept. Refused because a silently dropped filter returns more rows than you asked for. |
| 400 | window_exceeded | A company search asked for results past the search index's ceiling. Narrow the query, or read a market's companies at /api/v1/markets/<id>/companies, which has no ceiling. |
| 401 | unauthenticated | Missing, malformed, unknown or revoked credential. |
| 402 | subscription_required | The credential is valid but the account's subscription does not cover this scope's product. Resolve it from the billing page. |
| 403 | forbidden | The credential does not hold the scope this route needs. |
| 404 | not_found | No such object for this credential. Markets and watches use 404 for another account's object too, so a response never confirms that an id exists. |
| 405 | method_not_allowed | This route does not accept that method. |
| 409 | cycle_active | A queued or running cycle blocks this work. The body carries that cycle. |
| 409 | external_worker_failed | The worker reported a failure for this job. |
| 409 | job_allowance_full | This project already holds its limit of open stage jobs. |
| 409 | job_cancelled | This job was cancelled. |
| 409 | job_expired | This job passed its deadline. Retry it to get a fresh one. |
| 409 | job_not_claimed | This job is unclaimed, or claimed by another credential. |
| 409 | job_not_open | This stage job has already been completed, cancelled or expired. |
| 409 | lease_expired | The claim lease ran out. Claim the job again. |
| 422 | idempotency_conflict | This idempotency key was already used for a different request. Generate a new key and retry. |
| 422 | validation_failed | The request was understood and refused. errors names the fields and stable codes. |
| 429 | burst_limited | Too many requests in the last minute. retry_after is seconds. Slow down and continue. |
| 429 | daily_row_limit | The account's shared daily row budget is spent. Every surface that returns rows (feeds, exports, API) shares this budget. |
| 429 | rate_limited | The account's daily request allowance is spent. |
| 500 | internal_error | Ours. The request_id is what to quote. |
| 503 | api_disabled | This part of the API is switched off globally. |
| 503 | search_unavailable | The search index is unreachable. Retry shortly. |